C++ 如何绑定winsock端口';服务器和多个客户端c++;?

C++ 如何绑定winsock端口';服务器和多个客户端c++;?,c++,multithreading,C++,Multithreading,我有一个服务器程序,假设它监听8888端口。假设我从多个客户端连接到服务器,并为每个客户端维护线程。现在,当一个新的客户端被线程添加到服务器中时。服务器与最新的一个进行交互,当该线程关闭时,我在向上一个客户端发送消息时收到连接重置错误(10054)。所以我想为客户端绑定一个端口,每当创建线程时,我都想存储特定的端口号并响应客户端,这样winsock上就不会出现连接重置问题。有人能给我推荐客户机代码的模型吗?或者有没有办法解决这个问题? //我正在考虑本地主机,这样Ip地址就不会改变 //wins

我有一个服务器程序,假设它监听8888端口。假设我从多个客户端连接到服务器,并为每个客户端维护线程。现在,当一个新的客户端被线程添加到服务器中时。服务器与最新的一个进行交互,当该线程关闭时,我在向上一个客户端发送消息时收到连接重置错误(10054)。所以我想为客户端绑定一个端口,每当创建线程时,我都想存储特定的端口号并响应客户端,这样winsock上就不会出现连接重置问题。有人能给我推荐客户机代码的模型吗?或者有没有办法解决这个问题? //我正在考虑本地主机,这样Ip地址就不会改变 //winsock的连接重置错误为10054(WSAGetLastError())

//服务器代码

#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#define _WIN32_WINNT 0x501
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <pthread.h>
#include <iostream>
// Need to link with Ws2_32.lib
#pragma comment (lib, "Ws2_32.lib")
// #pragma comment (lib, "Mswsock.lib")
using namespace std;
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
void *connection_handler(void *);
static SOCKET ClientSocket = INVALID_SOCKET;
int iSendResult;
int iResult;

// class Authenticate {
//     bool getAuthenticated() {

//     }
// };





int __cdecl main(void) 
{
    WSADATA wsaData;
    int *new_sock;

    SOCKET ListenSocket = INVALID_SOCKET;


    struct addrinfo *result = NULL;
    struct addrinfo hints;
    pthread_t sniffer_thread[5];
    int i = 0;

    char recvbuf[DEFAULT_BUFLEN];
    int recvbuflen = DEFAULT_BUFLEN;

    // Initialize Winsock
    iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
    if (iResult != 0) {
        printf("WSAStartup failed with error: %d\n", iResult);
        return 1;
    }

    ZeroMemory(&hints, sizeof(hints));
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_protocol = IPPROTO_TCP;
    hints.ai_flags = AI_PASSIVE;

    // Resolve the server address and port
    iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
    if ( iResult != 0 ) {
        printf("getaddrinfo failed with error: %d\n", iResult);
        WSACleanup();
        return 1;
    }

    // Create a SOCKET for connecting to server
    ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
    if (ListenSocket == INVALID_SOCKET) {
        printf("socket failed with error: %ld\n", WSAGetLastError());
        freeaddrinfo(result);
        WSACleanup();
        return 1;
    }

    // Setup the TCP listening socket
    iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
    if (iResult == SOCKET_ERROR) {
        printf("bind failed with error: %d\n", WSAGetLastError());
        freeaddrinfo(result);
        closesocket(ListenSocket);
        WSACleanup();
        return 1;
    }

    //freeaddrinfo(result);

        printf("starting\n");
        iResult = listen(ListenSocket, 5);
        if (iResult == SOCKET_ERROR) {
            printf("listen failed with error: %d\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }
        int c = sizeof(struct sockaddr_in);
        // Accept a client socket
    while( i < 5) {
        ClientSocket = accept(ListenSocket, (struct sockaddr *)&hints, (socklen_t*)&c);
        if (ClientSocket == INVALID_SOCKET) {
            printf("accept failed with error: %d\n", WSAGetLastError());
            closesocket(ListenSocket);
            WSACleanup();
            return 1;
        }

        printf("Connection accepted\n");

        if( pthread_create( &sniffer_thread[i] , NULL ,  connection_handler , NULL) < 0)
        {
            perror("could not create thread");
            return 1;
        }
        //cout << sniffer_thread[i].get_id();
         i++;
        //Now join the thread , so that we dont terminate before the thread
    }
        printf("Handler assigned\n");
        for (int i = 0; i < 5; ++i)
        {
             pthread_join(sniffer_thread[i] , NULL);
        }


    if (ClientSocket < 0)
    {
        perror("accept failed");

        return 1;
    }

    return 0;
}
void *connection_handler(void *socket_desc)
{
    //Get the socket descriptor
    char recvbuf[2000];

     do {
        cout << GetCurrentThreadId()<<endl;
        iResult = recv(ClientSocket, recvbuf, 2000, 0);
        printf("%s%d\n",recvbuf,strlen(recvbuf) );
            if(strcmp(recvbuf,"quit") == 0)
                closesocket(ClientSocket);
        recvbuf[iResult] = '\0';
        //fflush(stdout);
        if (iResult > 0) {
            printf("Client Says: \t%s\n", recvbuf);
            fflush(stdin);
            fgets(recvbuf,100,stdin);
            int ln = strlen(recvbuf)-1;
            if(recvbuf[ln] == '\n')
                recvbuf[ln] = '\0';

            iSendResult = send( ClientSocket, recvbuf, strlen(recvbuf), 0 );
            fflush(stdout);
            if (iSendResult == SOCKET_ERROR) {
                printf("send failed with error: %d\n", WSAGetLastError());
                closesocket(ClientSocket);
                WSACleanup();
            }
            printf("Bytes sent from server: %d\n", iSendResult);
        }
        else if (iResult == 0)
            printf("Connection closing...\n");
        else  {
            printf("recv failed with error: %d\n", WSAGetLastError());

        }

    } while (iResult > 0);
//Free the socket pointer
    closesocket(ClientSocket);
    return 0;
}
#未定义UNICODE
#定义WIN32_精益_和_平均值
#定义_WIN32_WINNT 0x501
#包括
#包括
#包括
#包括
#包括
#包括
#包括
//需要链接到Ws2_32.lib
#pragma注释(lib,“Ws2_32.lib”)
//#pragma注释(lib,“Mswsock.lib”)
使用名称空间std;
#定义默认值\u BUFLEN 512
#定义默认_端口“27015”
void*连接处理程序(void*);
静态套接字ClientSocket=无效的\u套接字;
int iSendResult;
国际结果;
//类验证{
//bool getAuthenticated(){
//     }
// };
内部cdecl干管(无效)
{
WSADATA WSADATA;
int*新袜子;
套接字ListenSocket=无效的\u套接字;
struct addrinfo*result=NULL;
结构addrinfo提示;
pthread_t sniffer_线程[5];
int i=0;
char recvbuf[默认值];
int recvbuflen=默认值;
//初始化Winsock
iResult=WSAStartup(MAKEWORD(2,2)和wsaData);
如果(iResult!=0){
printf(“WSAStartup失败,错误:%d\n”,iResult);
返回1;
}
零内存(&提示,sizeof(提示));
hits.ai_family=AF_INET;
hits.ai_socktype=SOCK_流;
hits.ai_protocol=IPPROTO_TCP;
hits.ai_flags=ai_被动;
//解析服务器地址和端口
iResult=getaddrinfo(NULL、默认端口、提示和结果);
如果(iResult!=0){
printf(“getaddrinfo失败,错误:%d\n”,iResult);
WSACleanup();
返回1;
}
//创建用于连接到服务器的套接字
ListenSocket=socket(结果->ai_族,结果->ai_socktype,结果->ai_协议);
if(ListenSocket==无效的_套接字){
printf(“套接字失败,错误:%ld\n”,WSAGetLastError());
freeaddrinfo(结果);
WSACleanup();
返回1;
}
//设置TCP侦听套接字
iResult=bind(ListenSocket,result->ai_addr,(int)result->ai_addrlen);
if(iResult==SOCKET\u错误){
printf(“绑定失败,错误:%d\n”,WSAGetLastError());
freeaddrinfo(结果);
闭合插座(ListenSocket);
WSACleanup();
返回1;
}
//freeaddrinfo(结果);
printf(“启动\n”);
iResult=侦听(ListenSocket,5);
if(iResult==SOCKET\u错误){
printf(“侦听失败,错误为:%d\n”,WSAGetLastError());
闭合插座(ListenSocket);
WSACleanup();
返回1;
}
int c=sizeof(结构sockaddr_in);
//接受客户端套接字
而(i<5){
ClientSocket=accept(ListenSocket,(struct sockaddr*)和hints,(socklen\u t*)和c);
if(ClientSocket==无效的_SOCKET){
printf(“接受失败,错误:%d\n”,WSAGetLastError());
闭合插座(ListenSocket);
WSACleanup();
返回1;
}
printf(“已接受连接”);
if(pthread\u create(&sniffer\u thread[i],NULL,connection\u handler,NULL)<0)
{
perror(“无法创建线程”);
返回1;
}

//如果为每个连接的客户端创建一个单独的线程,为什么服务器只与最后一个客户端通信?通信应该并行执行,对吗?您有代码要显示吗?另一个主题是为什么每个客户端一个线程不是好方法,应该使用线程池。我已经更新了服务器代码。
iResult
iSendResult
是全局变量,但由多个线程使用。这些变量在本地上下文中使用,因此我宁愿将它们移动到它们所属的范围,而不是同步它们。ok@karastojko我已经做了更改,但仍然有一个问题。在我的情况下,我从客户端获取输入,并将其发送到服务器反之亦然。连接重置问题已解决,但winsock错误10053即将出现。[链接]()。也请帮我解决这个问题。提前谢谢;)我相信您在
ClientSocket
中也有类似的情况。所有线程都使用同一个变量,因此所有连接的客户端都使用它-听起来像是个麻烦。我相信您应该将该变量设置为本地变量,并将其传输到
connection\u handler()
。这样,一个线程使用自己的客户端套接字进行通信。