VC++ TCP網絡控制檯程序

在Windows7系統下,採用工具爲VS2008,Win32控制檯應用程序,編寫一個基於TCP的Client/Server網絡程序。
1、服務器端代碼
[cpp] view plain copy

#include <WinSock2.h>  
#include <stdio.h>  

#define SERVERPORT 6000 //服務端口號  

int main(int argc, char *argv[])  
{  
    //加載套接字庫  
    WORD wVersionRequested;//用於保存WinSock庫的版本號  
    WSADATA wsaData;  
    int err;  

    printf("This is a Server side application!\n");  

    wVersionRequested = MAKEWORD(2,2);  

    err = WSAStartup( wVersionRequested, &wsaData);  
    if (err != 0)  
    {  
        printf("WSAStartup() called failed!\n");  
        return -1;  
    }  
    else  
    {  
        printf("WSAStartup() called successful!\n");  
    }  

    if (LOBYTE(wsaData.wVersion) != 2 ||  
          HIBYTE(wsaData.wVersion) != 2)  
    {  
        //若不是所請求的版本號2.2,則終止WinSock庫的使用  
        WSACleanup();  
        return -1;  
    }  

    //創建用於監聽的套接字  
    SOCKET sockServer = socket(AF_INET, SOCK_STREAM, 0);  
    if(sockServer == INVALID_SOCKET)  
    {  
        printf("socket() called failed! ,error code is: %d", WSAGetLastError());  
        return -1;  
    }  
    else  
    {  
        printf("socket() called successful!\n");  
    }  

    //填充服務器端套接字結構  
    SOCKADDR_IN addrServer;  
    addrServer.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//將主機字節順序轉換成TCP/IP網絡字節順序  
    addrServer.sin_family = AF_INET;  
    addrServer.sin_port = htons(SERVERPORT);  

    //將套接字綁定到一個本地地址和端口上  
    err = bind(sockServer, (SOCKADDR*)&addrServer, sizeof(SOCKADDR));  
    if (err == SOCKET_ERROR)  
    {  
        printf("bind() called failed! The error code is: %d\n", WSAGetLastError());  
        return -1;  
    }  
    else  
    {  
        printf("bind() called successful\n");  
    }  
    //將套接字設置爲監聽模式,準備接收客戶請求  
    err = listen(sockServer, 5);  
    if (err == SOCKET_ERROR)  
    {  
        printf("listen() called failed! The error code is: %d\n", WSAGetLastError());  
        return -1;  
    }  
    else  
    {  
        printf("listen() called successful!\n");  
    }  

    SOCKADDR_IN addrClient; //保存發送請求連接的客戶端的套接字信息  
    int len = sizeof(SOCKADDR);  

    while(1)  
    {  
        //等待客戶請求到來  
        SOCKET sockConn = accept(sockServer, (SOCKADDR*)&addrClient, &len);  
        if (sockConn == INVALID_SOCKET)  
        {  
            printf("accept() called falied! The error code is: %d\n", WSAGetLastError());  
        }  
        else  
        {  
            printf("The Server receive a new client connection!\n");  
        }  

        char sendBuf[100];  
        sprintf_s(sendBuf, 100, "Welcome %s",inet_ntoa(addrClient.sin_addr));  

        //發送數據  
        send(sockConn, sendBuf, strlen(sendBuf)+1 , 0);  
        char recvBuf[100];  
        //接收數據  
        recv(sockConn, recvBuf, 100, 0);  
        //打印接收到的數據  
        printf("receive data from client side [%s,%d] is: %s\n", inet_ntoa(addrClient.sin_addr), addrClient.sin_port,  
                              recvBuf);  
        closesocket(sockConn);  //關閉連接套接字  
    }  

    return 0;  
}  

2、客戶端代碼
[cpp] view plain copy

#include <WinSock2.h>  
#include <stdio.h>  

#define SERVERPORT 6000 //服務端口號  

#pragma comment(lib, "WS2_32.lib");  

int main(int argc, char *argv[])  
{  
    //加載套接字庫  
    WORD wVersionRequested;  
    WSAData wsaData;  
    int err;  

    printf("This is a Client side application!\n");  

    wVersionRequested = MAKEWORD( 2, 2 );  

    err = WSAStartup(wVersionRequested, &wsaData);  
    if (err != 0 )  
    {  
        /* Tell the user that we could not find a usable */  
        /* WinSock DLL.                                  */  
        printf("WSAStartup() called failed!\n");  
        return -1;  
    }  
    else  
    {  
        printf("WSAStartup() called successful!\n");  
    }  

    if ( LOBYTE( wsaData.wVersion ) != 2 ||  
        HIBYTE( wsaData.wVersion ) != 2 ) {  
            /* Tell the user that we could not find a usable */  
            /* WinSock DLL.                                  */  
            WSACleanup( );  
            return -1;   
    }  

    /* The WinSock DLL is acceptable. Proceed. */  

    //創建套接字  
    SOCKET sockClient = socket(AF_INET, SOCK_STREAM, 0);  
    if(sockClient == INVALID_SOCKET)  
    {  
        printf("socket() called failed! ,error code is: %d", WSAGetLastError());  
        return -1;  
    }  
    else  
    {  
        printf("socket() called successful!\n");  
    }  

    //需要連接的服務端套接字結構信息  
    SOCKADDR_IN addrServer;  
    addrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");//設定服務器的IP地址  
    addrServer.sin_family = AF_INET;  
    addrServer.sin_port = htons(SERVERPORT);//設定服務器的端口號(使用網絡字節序)  

    //向服務器發出連接請求  
    err = connect(sockClient, (SOCKADDR*)&addrServer, sizeof(SOCKADDR));  
    if (err == SOCKET_ERROR)  
    {  
        printf("connect() called failed! The error code is: %d\n", WSAGetLastError());  
        return -1;  
    }  
    else  
    {  
        printf("connect() called successful\n");  
    }  

    //接收數據  
    char recvBuf[100]={0};  
    recv(sockClient, recvBuf, 100, 0);  
    printf("receive data from server side is: %s\n", recvBuf);  

    //發送數據  
    send(sockClient, "This is a client side!\n", strlen("This is a client side!\n")+1, 0);  

    //關閉套接字  
    closesocket(sockClient);  

    //終止套接字庫的使用  
    WSACleanup();  

    return 0;  
}  

另外,需要注意的是需要在服務器和客戶端都需要鏈接WinSock靜態鏈接庫Ws2_32.lib,有兩種添加方法
方法一:在工程配置屬性中添加
假如創建一個名爲TCPClient的Win32控制檯應用程序
在VC2008中添加靜態鏈接庫WS2_32.lib的方法如下:
(1)切換到TCPServer的【Solution Explorer】,選擇菜單【Project】->【TCPClient Properties】
(2)在TCPClient Properties Pages對話框中,依次選擇【Configuration Properties】->【Linker】->【Input】,在右側的【Addtional Dependencies】中添加Ws2_32.lib庫。
如下如所示:

服務器TCPServer也需要鏈接Ws2_32.lib庫,方法和客戶端TCPClient一樣。

程序結果運行如下:
先啓動服務器端程序TCPServer,結果如下:

再啓動客戶端TCPClient,客戶端結果如下:

服務器端TCPServer結果如下:

方法二:在代碼中添加

#pragma comment(lib, "WS2_32.lib");

參考資料:
1、《VC++深入詳解》 第14章網絡編程 ,孫鑫主編
2、MSDN幫助文檔

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章