Windows socket网络编程-TCP通信实例代码

    xiaoxiao2025-02-10  19

    步骤如下:

    服务器:

    1.初始化

    包含Winsock2.h头文件和引用ws2_32.lib静态库。 #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib")   

    WSAStartUp函数

    2.创建侦听套接字

    socket

    3.绑定ip和端口,绑定侦听套接字

    SOCKADDR_IN

    bind

    4.开启监听

    listen

    5.等待客户端连接

    accept

    6.收发数据

    recv/send

     

    客户端:

    1.初始化

    包含Winsock2.h头文件和引用ws2_32.lib静态库。 #include <WinSock2.h> #pragma comment(lib,"ws2_32.lib")   

    WSAStartUp函数

    2.创建连接套接字

    socket

    3.地址解析并连接服务器

    SOCKADDR_IN

    connect

    4.收发数据

    recv/send

    -------------------------Code----------------------------------------

    服务器代码如下:

    #include "stdafx.h" #include <WinSock2.h> #include <WS2tcpip.h>  #pragma comment(lib,"ws2_32.lib")    #include <stdio.h> 

    int main()   {       /// 初始化socket       WSADATA wsaData;       WORD version = MAKEWORD(2,2);       int result = 0;       result = WSAStartup(version, &wsaData);       if (0 != result)       {           std::cout << "WSAStartup() error." << std::endl;           return -1;       }          /// 创建侦听socket        SOCKET socketListen;       socketListen = socket(AF_INET, SOCK_STREAM, 0);       if (socketListen == INVALID_SOCKET)       {           WSACleanup();           std::cout << "socket() error." << std::endl;           return -1;       }          /// 服务器地址结构        sockaddr_in svrAddress;       svrAddress.sin_family = AF_INET;       svrAddress.sin_addr.s_addr = INADDR_ANY;       svrAddress.sin_port = htons(8000);          /// 绑定服务器套接字        result = bind(socketListen, (sockaddr*)&svrAddress, sizeof(svrAddress));       if (result == SOCKET_ERROR)       {           closesocket(socketListen);           WSACleanup();           std::cout << "bind() error." << std::endl;           return -1;       }          /// 开启监听       result = listen(socketListen, 5);       if (result == SOCKET_ERROR)       {           closesocket(socketListen);           WSACleanup();           std::cout << "listen() error." << std::endl;           return -1;       }       std::cout << "服务器启动成功,监听端口:" << ntohs(svrAddress.sin_port) << std::endl;          /// select模型        fd_set allSockSet;        FD_ZERO(&allSockSet);           FD_SET(socketListen, &allSockSet); // 将socketListen加入套接字集合中           while (true)       {           fd_set readSet;           FD_ZERO(&readSet);                    //初始化可读队列         readSet = allSockSet;                       result = select(0, &readSet, NULL, NULL, NULL);           if (result == SOCKET_ERROR)           {               std::cout << "select() error." << std::endl;               break;           }              if (FD_ISSET(socketListen, &readSet))           {               sockaddr_in clientAddr;               int len = sizeof(clientAddr);                        SOCKET clientSocket = accept(socketListen, (sockaddr*)&clientAddr, &len);                      if (clientSocket == INVALID_SOCKET)               {                   std::cout << "accept() error." << std::endl;                   break;               }               FD_SET(clientSocket, &allSockSet);   /// 将新创建的套接字加入到集合中                   char ipAddress[16] = { 0 };               inet_ntop(AF_INET, &clientAddr, ipAddress, 16);               std::cout << "有新的连接[" << ipAddress << ":" << ntohs(clientAddr.sin_port)                   << "], 目前客户端的数量为:" << allSockSet.fd_count - 1 << std::endl;       //去掉一个侦听套接字                continue;           }  

            for (u_int i = 0; i < allSockSet.fd_count; ++i)           {               SOCKET socket = allSockSet.fd_array[i];                  sockaddr_in clientAddr;               int len = sizeof(clientAddr);               getpeername(socket, (struct sockaddr *)&clientAddr, &len);      //获得与套接口相连的远程协议地址             char ipAddress[16] = { 0 };               inet_ntop(AF_INET, &clientAddr, ipAddress, 16);                  /// 可读性监视,可读性指有连接到来、有数据到来、连接已关闭、重置或终止               if (FD_ISSET(socket, &readSet))               {                   char bufRecv[100];                   result = recv(socket, bufRecv, 100, 0);                   if (result == SOCKET_ERROR)                   {                       DWORD err = WSAGetLastError();                       if (err == WSAECONNRESET)       /// 客户端的socket没有被正常关闭,即没有调用closesocket                       {                           std::cout << "客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port) << "]被强行关闭, ";                       }                       else                       {                           std::cout << "recv() error," << std::endl;                       }                                  closesocket(socket);                       FD_CLR(socket, &allSockSet);                          std::cout << "目前客户端的数量为:" << allSockSet.fd_count - 1 << std::endl;                       break;                   }                   else if (result == 0)               /// 客户端的socket调用closesocket正常关闭                   {                       closesocket(socket);                       FD_CLR(socket, &allSockSet);                          std::cout << "客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port)                            << "]已经退出,目前客户端的数量为:" << allSockSet.fd_count - 1 << std::endl;                       break;                   }                      bufRecv[result] = '\0';                   std::cout << "来自客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port)                       << "]的消息:" << bufRecv << std::endl;                                    char szSend[256] = "朕已经收到,你可以滚了!";                 send(socket, szSend, strlen(szSend), 0);             }           }       }          for (u_int i = 0; i < allSockSet.fd_count; ++i)       {           SOCKET socket = allSockSet.fd_array[i];           closesocket(socket);       }          WSACleanup();       return 0;   } 

     

    客户端代码:

    #include "stdafx.h" #include <iostream>   #include <WS2tcpip.h>   #include <WinSock2.H>   using namespace std; #pragma comment(lib, "ws2_32.lib")  

    #define SERVER_ADDRESS      "192.168.1.179"   #define SERVER_PORT         8000  

    #define SOCKET_NUM          120       /// 客户端socket的个数,修改该值可以改变连接到服务器的客户端个数  

    SOCKET socketClient;

    char g_szBuf[512] = "";

    HANDLE hMutex;

    void Input();

    void Recv();

    DWORD WINAPI ThreadProc(     _In_ LPVOID lpParameter     );

    DWORD WINAPI SendDataThreadProc(     _In_ LPVOID lpParameter     );

    int main()   {       WORD wVersionRequested = MAKEWORD(2, 2);       WSADATA wsaData;       int err = WSAStartup(wVersionRequested, &wsaData);       if (err != 0) return 1;  

        if (LOBYTE(wsaData.wVersion) != 2 ||           HIBYTE(wsaData.wVersion) != 2)        {           WSACleanup();           std::cout << "WSAStartup() error." << std::endl;           return -1;       }    

        socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);       if (socketClient == INVALID_SOCKET)       {           WSACleanup();           std::cout << "socket() error." << std::endl;           return -1;       }  

        SOCKADDR_IN server;       memset(&server, 0, sizeof(SOCKADDR_IN));       server.sin_family = AF_INET;       server.sin_port = htons(SERVER_PORT);       inet_pton(server.sin_family, SERVER_ADDRESS, &server.sin_addr);  

        err = connect(socketClient, (struct sockaddr *)&server, sizeof(SOCKADDR_IN));       if (err == SOCKET_ERROR)       {           std::cout << "connect() error." << std::endl;           closesocket(socketClient);           WSACleanup();           return -1;       }  

        hMutex = CreateMutex(NULL, false, (LPCWSTR)"MutexOne");     if (NULL == hMutex)     {         printf("创建互斥对象失败!\n");         return -1;     }

        DWORD dwThreadId = 0;

        /*HANDLE hThread = CreateThread(NULL, NULL, &SendDataThreadProc, NULL, 0, &dwThreadId);     if (NULL == hThread)     {     printf("创建发送线程失败!\n");     return -1;     }*/

        HANDLE hThread2 = CreateThread(NULL, NULL, &ThreadProc, NULL, 0, &dwThreadId);     if (NULL == hThread2)     {         printf("创建接收线程失败!\n");         return -1;     }

     

        Input(); //    Recv();          closesocket(socketClient);     WSACleanup();  

        return 0;   }  

    void Input() {     while (true)     {         WaitForSingleObject(hMutex, INFINITE);         char szInput[256] = "";         printf("Me:");         scanf("%s", szInput);         if (strcmp(szInput, "exit") == 0)         {             break;         }         else         {             send(socketClient, szInput, strlen(szInput), 0);         } //        printf("\n");         ReleaseMutex(hMutex);              } }

    void Recv() {     while (true)     {                  recv(socketClient, g_szBuf, sizeof(g_szBuf), 0);         printf("Me Recv Form Server:%s\n", g_szBuf);

                 } }

    DWORD WINAPI ThreadProc(_In_ LPVOID lpParameter) {          while (true)     {         WaitForSingleObject(hMutex, INFINITE);         recv(socketClient, g_szBuf, sizeof(g_szBuf), 0);         printf("Recv Form Server:%s\n\n", g_szBuf);         ReleaseMutex(hMutex);     }

        return 0; }

    DWORD WINAPI SendDataThreadProc(_In_ LPVOID lpParameter) {          while (true)     {         WaitForSingleObject(hMutex, INFINITE);         char szInput[256] = "";         printf("Me:");         scanf("%s", szInput);         if (strcmp(szInput, "exit") == 0)         {             break;         }         else         {                          send(socketClient, szInput, strlen(szInput), 0);                      }         printf("\n");         ReleaseMutex(hMutex);     }     

        return 0; }

    最新回复(0)