1. 程式人生 > WINDOWS開發 >TCP協議(三)之Windows實現

TCP協議(三)之Windows實現

tcp 程式設計一般的步驟:
server(服務端)
1.new 個 socket
2.bind (IP,port)
3.listen,等待客戶端的連線
4.accept 接受客戶端的連線
5.接收(recv) 傳送資料(send)
6.關閉連線

client(客戶端)
1.new 個 socket
2.bind(ip,port)
3.connect (server.ip,server,port)
4.recv() /send()
5.關閉連線

2.程式

伺服器程式

#include <stdlib.h>
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"Ws2_32.lib ")

int main()
{
    WSADATA wsaData;
    struct sockaddr_in servAddr;
    struct sockaddr_in cliAddr;

    if (WSAStartup(MAKEWORD(2,2),&wsaData))
    {
        printf("Error:RequestWindowsSocketLibrary failed!\n");
        return 0;
    }
    /* 設定IP地址 */
    memset(&servAddr,sizeof(servAddr));
    servAddr.sin_addr.s_addr = htonl(INADDR_ANY); //繫結本機IP
    //servAddr.sin_addr.s_addr = inet_addr("192.168.1.53");

    /* 設定埠 */
    servAddr.sin_family = AF_INET;
    servAddr.sin_port = htons(3000); //埠為3000

    /* 建立套接服務字 */
    SOCKET serverSocket;
    serverSocket = socket(AF_INET,SOCK_STREAM,0);
    if (serverSocket == INVALID_SOCKET)
    {
        printf("Error:CreatServerSocket failed!\n");
        return 0;
    }

        /* 繫結伺服器套接字 */
    if (bind(serverSocket,(sockaddr*)&servAddr,sizeof(sockaddr)) == SOCKET_ERROR) 
    {
        printf("ERROR:Bind failed!\n");
        return 0;
    }

    /* 監聽埠 */
    if (listen(serverSocket,20) == SOCKET_ERROR)
    {
        closesocket(serverSocket);
        WSACleanup();
        printf("ERROR:Listen failed!\n");
        return 0;
    }
    printf("linstening:%dport...\n",ntohs(servAddr.sin_port));

    /* 阻塞方式等待accept */
    int len = sizeof(cliAddr);
    SOCKET clientSocket;
    clientSocket = accept(serverSocket,(sockaddr*)&cliAddr,&len);
    printf("Connected:%s \r\n",inet_ntoa(cliAddr.sin_addr));

    /* 接受訊息 */
    char recvBuf[100] = { 0 };
    recv(clientSocket,recvBuf,sizeof(recvBuf),0);

    /* 傳送訊息 */
    send(clientSocket,100,NULL);

    closesocket(clientSocket);
    WSACleanup();
    system("pause");
    return 1;
}

客戶端程式碼

#include "stdlib.h"
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib,"ws2_32.lib")  //載入 ws2_32.dll

int main()
{
    //初始化DLL
    //主版本號(低位元組)為2,副版本號為2,返回 0x0202
    WORD sockVersion = MAKEWORD(2,2);         
    WSADATA wsaData;
    //WSAStartup() 函式執行成功後,會將與 ws2_32.dll 有關的資訊寫入 WSAData 結構體變數
    //(只需關注前兩個成員即可)
    if (WSAStartup(sockVersion,&wsaData) != 0)   
        return 0;

    //建立套接字,socket() 函式用來建立套接字,確定套接字的各種屬性
    //IPv4 地址、面向連線的資料傳輸方式、TCP 傳輸協議
    SOCKET sock = socket(PF_INET,IPPROTO_TCP);

    //向伺服器發起請求,將建立的套接字與IP地址 101.76.220.219、埠 3000 繫結:
    sockaddr_in sockAddr;
    memset(&sockAddr,sizeof(sockAddr));  
    sockAddr.sin_family = PF_INET;  

    //32位IP地址,s_addr 是一個整數(unsigned long),而IP地址是一個字串,
    //所以需要 inet_addr() 函式進行轉換
    sockAddr.sin_addr.s_addr = inet_addr("101.76.218.229");  

    //16位的埠號,埠號需要用 htons() 函式轉換,0~1023 的埠一般由系統分配給特定的服務程式,
    //儘量在 1024~65536 之間分配埠號。
    sockAddr.sin_port = htons(3000);                        
   
    //強制型別轉換,伺服器端要用 bind() 函式將套接字與特定的IP地址和埠繫結起來,
    //只有這樣,流經該IP地址和埠的資料才能交給套接字處理
    while (connect(sock,(SOCKADDR*)& sockAddr,sizeof(SOCKADDR)) == SOCKET_ERROR)
    {
        printf("連線失敗\n");
        Sleep(1000);
    }
    printf("成功連線到伺服器!\n");

    char sendBuf[100] = {"Hello World"};
    send(sock,sendBuf,NULL);

    char recvBuf[100] = { 0 };
    recv(sock,0);  

    closesocket(sock);
    WSACleanup();

    for (int i = 0; i < 12; i++)
    {
        printf("%c",recvBuf[i]);
    }

    system("pause");
    return 1;
}