多路Select Socket编程

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/qq_33048069/article/details/79304502

/**************客户端代码 *******************/

#include <iostream>  
#include <WS2tcpip.h>  
#include <WinSock2.H>  


#pragma comment(lib, "ws2_32.lib")  


#define SERVER_ADDRESS      "127.0.0.1"  
#define SERVER_PORT         8000  


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


#pragma pack(push,1)
struct MyStruct
{
    unsigned int a;
    unsigned int b;
};
#pragma pack()


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;  
    }  


    SOCKET allSocketClients[SOCKET_NUM];  
    for (int i = 0; i < SOCKET_NUM; i ++)  
    {  
        SOCKET socketClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);  
        if (socketClient == INVALID_SOCKET)  
        {  
            WSACleanup();  
            std::cout << "socket() error." << std::endl;  
            return -1;  
        }  
        allSocketClients[i] = socketClient;  
    }  


    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);  


    for (int i = 0; i < SOCKET_NUM; i++)  
    {  
        SOCKET socketClient = allSocketClients[i];  
        err = connect(socketClient, (struct sockaddr *)&server, sizeof(SOCKADDR_IN));  
        if (err == SOCKET_ERROR)  
        {  
            std::cout << "connect() error." << std::endl;  
            closesocket(socketClient);  
            WSACleanup();  
            return -1;  
        }  
    }  


    for (int i = 0; i < SOCKET_NUM; i++)  
    {  
        SOCKET socketClient = allSocketClients[i]; 
        MyStruct st;
        st.a =200;
        st.b =300;
        char message[100] = { 0 };  
        memcpy(message,&st,sizeof(st)); 
        int iSendData = send(socketClient, message, sizeof(st), 0);  
    }  


    for (int i = 0; i < SOCKET_NUM; i++)  
    {  
        SOCKET socketClient = allSocketClients[i];  
        closesocket(socketClient);  
    }  


    WSACleanup();  


    return 0;  

}  


/***************服务端代码*************************

#include <iostream>
#include <stdio.h>
#include "TcpBase.h"


#pragma pack(push,1)
struct MyStruct
{
    unsigned int a;
    unsigned int b;
};
#pragma pack()


class TcpSer:public TcpBase
{
public:
    TcpSer()
        :_fp(NULL)
    {
        bufRecv = new char[100];
        memset(bufRecv,0,100);
    }
    virtual~TcpSer()
    {
       delete []bufRecv;
       bufRecv = NULL;
    }


 static unsigned long __stdcall RecvSocket(void* ptr)
 {
     TcpSer* ptrSer = (TcpSer* )(ptr);
    
     struct timeval tv = {2, 0};   
     memset(&ptrSer->allSockSetT,0,sizeof(ptrSer->allSockSetT));
     FD_SET(ptrSer->_sSocket, &ptrSer->allSockSetT); // 将socketListen加入套接字集合中 


     while (true)  
     { 
         fd_set fdOld = ptrSer->allSockSetT;//此地方不写的话,会造成 select错误   
         int result = select(0, &fdOld, NULL, NULL, &tv);  
         if (result == SOCKET_ERROR)  
         {  
             std::cout << "listen() error." << std::endl;  
             break;
         }
         if(result == 0)
         {
             continue;
         }
         
         if(result>0)
         {
             for(int i = 0;i < ptrSer->allSockSetT.fd_count; i++)    
             {    
                 if (FD_ISSET(ptrSer->allSockSetT.fd_array[i],&fdOld))    
                 {    
                     //如果socket是服务器,则接收连接    
                     if (ptrSer->allSockSetT.fd_array[i] == ptrSer->_sSocket)    
                     {    
                         SOCKET clientSocket = ptrSer->Accpect();        
                         if (clientSocket == INVALID_SOCKET)  
                         {  
                             std::cout << "accept() error." << std::endl;  
                             break;  
                         }  
                         FD_SET(clientSocket, &ptrSer->allSockSetT);   /// 将新创建的套接字加入到集合中   


                         std::cout << "], 目前客户端的数量为:" << ptrSer->allSockSetT.fd_count - 1 << std::endl;     
                     }    
                     else //非服务器,接收数据(因为fd是读数据集)    
                     {    
                         SOCKET socket = ptrSer->allSockSetT.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);  


                         result = ptrSer->RecvData(socket,( unsigned char*)ptrSer->bufRecv,100);


                         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, &ptrSer->allSockSetT);  


                             std::cout << "目前客户端的数量为:" << ptrSer->allSockSetT.fd_count - 1 << std::endl;  
                             break;  
                         }  
                         else if (result == 0)               /// 客户端的socket调用closesocket正常关闭  
                         {  
                             closesocket(socket);  
                             FD_CLR(socket, &ptrSer->allSockSetT);  


                             if(ptrSer->allSockSetT.fd_count >0)
                             {
                                 std::cout << "客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port)   
                                     << "]已经退出,目前客户端的数量为:" << ptrSer->allSockSetT.fd_count - 1 << std::endl; 
                             }
                             else
                             {
                                 std::cout << "客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port)   
                                     << "]已经退出,目前客户端的数量为:" << ptrSer->allSockSetT.fd_count << std::endl; 
                             }


                             break;  
                         }  


                         int dataSize = ptrSer->SendData(socket,(const unsigned char*)ptrSer->bufRecv,result);
                         MyStruct *ptr =(MyStruct*)(ptrSer->bufRecv);


                         ptrSer->bufRecv[result] = '\0';  
                         std::cout << "来自客户端[" << ipAddress << ":" << ntohs(clientAddr.sin_port)  
                             << "]的消息:" << ptr->a <<" "<<ptr->b<<std::endl;    
                     }       
                 }    
             }
         }


         Sleep(200);
     }  




     return 0;
 }


private:
    fd_set allSockSetT;
    char *bufRecv;
    FILE *_fp; 


};


int main()  
{  
    /// 初始化socket 
    unsigned short iPort = 8000;
     TcpSer ser;
     ser.BindSocket(iPort);
     ser.ListenSocket(200);


    void *pThread = CreateThread(NULL,0,TcpSer::RecvSocket,&ser,0,NULL);


    WaitForSingleObject(pThread,0xFFFFFFFF);


    //for (u_int i = 0; i < allSockSetT.fd_count; ++i)  
    //{  
    //    SOCKET socket = allSockSetT.fd_array[i];  
    //    closesocket(socket);  
    //}  


    WSACleanup();  
    return 0;  
}  

猜你喜欢

转载自blog.csdn.net/qq_33048069/article/details/79304502