C++ c++;tcp服务器(windows OS)-recv()与服务器的连接超过1个时会延迟

C++ c++;tcp服务器(windows OS)-recv()与服务器的连接超过1个时会延迟,c++,windows,tcp,delay,C++,Windows,Tcp,Delay,当我试图仅使用一台客户端连接到服务器时,服务器上的recv()函数不会延迟 但是,当我启动客户端控制台超过1次(大约7次)时,在使用函数send()将数据包发送到服务器后,会有大约2000毫秒的延迟,直到服务器在is控制台中打印数据包 有没有不为每个客户端启动线程的解决方案?(Windows限制每个进程的线程数) 代码是使用Visual Studio 2008编译的,这是完整的服务器代码: #include <WinSock2.h> #include <ws2tcpip.h&g

当我试图仅使用一台客户端连接到服务器时,服务器上的
recv()
函数不会延迟

但是,当我启动客户端控制台超过1次(大约7次)时,在使用函数
send()
将数据包发送到服务器后,会有大约2000毫秒的延迟,直到服务器在is控制台中打印数据包

有没有不为每个客户端启动线程的解决方案?(Windows限制每个进程的线程数)

代码是使用Visual Studio 2008编译的,这是完整的服务器代码:

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

struct sslv3
{
#define max_clients 1024
private:
    int cClient;
public:
    SOCKET fd;
    int CurrentClient()
    {
        return cClient;
    }
    struct client
    {
        client()
        {
            Valid = false;
        }
        bool Valid;
        DWORD ip;
        WORD port;
        char ipstr[33];
        char portstr[33];
        SOCKET fd;
        void StrGen()
        {
            wsprintf(ipstr, "%d.%d.%d.%d", ip & 0xFF, (ip & 0xFF00)/0x100, (ip & 0xFF0000)/0x10000, (ip & 0xFF000000)/0x1000000);
            wsprintf(portstr, "%d", port);
        }
    } clients[max_clients];
    //
    sslv3(bool server_client)
    {
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2, 2), &wsaData);
        cClient = 0;
        fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        //
        DWORD timeout = 1;
        setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(DWORD));
    }
    int Bind(WORD port)
    {
        int ret = 0;
        sockaddr_in local;
        local.sin_addr.s_addr = htonl(INADDR_ANY);
        local.sin_family = AF_INET;
        local.sin_port = htons(port);
        if((ret = bind(fd, (struct sockaddr *)&local, sizeof(local)))
            != SOCKET_ERROR)
            listen(fd, SOMAXCONN);
        return ret;
    }
    int Accept()
    {
        SOCKET clientfd;
        sockaddr_in client;
        int addrlen = sizeof(client);
        clientfd = accept(fd, (struct sockaddr *)&client, &addrlen);
        if(clientfd == -1)
            return -1;
        clients[cClient].ip = client.sin_addr.S_un.S_addr;
        clients[cClient].port = client.sin_port;
        clients[cClient].StrGen();
        clients[cClient].fd = clientfd; 
        clients[cClient].Valid = true;
        //
        DWORD timeout = 1;
        setsockopt(clients[cClient].fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(DWORD));
        cClient++;
        if(cClient >= max_clients)
        {
            cClient = 0;
            return max_clients - 1;
        }
        return cClient - 1;
    }
    int Connect(char ip[], WORD port)
    {
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(ip);
        addr.sin_port = htons(port);
        return connect(fd, (const struct sockaddr*)&addr, sizeof(addr));
    }
    int Send(SOCKET sfd, void* buffer, int length)
    {
        return send(sfd, (char*)buffer, length, 0);
    }
    int Read(SOCKET sfd, void* buffer, int length)
    {
        return recv(sfd, (char*)buffer, length, 0);
    }
};

sslv3 cssl(true);

DWORD WINAPI ReadThread(void* args)
{
    while(true)
    {
        for(int j = 0; j <= cssl.CurrentClient(); j++)
        {
            if(cssl.clients[j].Valid)
            {
                char rpack[1024];
                for(int i = 0; i < sizeof(rpack); i++)
                    rpack[i] = 0;
                if(cssl.Read(cssl.clients[j].fd, rpack, sizeof(rpack)) > 0){
                    printf("%s:%s says: %s\n", cssl.clients[j].ipstr, cssl.clients[j].portstr, rpack);
                }
            }
        }
        Sleep(1);
    }
    return TRUE;
}

int main()
{
    cssl.Bind(1234);
    CreateThread(0,0,ReadThread,0,0,0);
    while(true)
    {
        Sleep(1);
        int cid = cssl.Accept();
        if(cid != -1){
            printf("%s:%s connected!\n", cssl.clients[cid].ipstr, cssl.clients[cid].portstr);
        }
    }
    return 0;
}
#包括
#包括
#pragma注释(lib,“ws2_32.lib”)
#包括
#包括
结构sslv3
{
#定义max_客户端1024
私人:
国际客户;
公众:
插座fd;
int CurrentClient()
{
归还客户;
}
结构客户端
{
客户()
{
有效=错误;
}
布尔有效;
叶德沃德;
字端口;
char-ipstr[33];
char-portstr[33];
插座fd;
void StrGen()
{
wsprintf(ipstr,“%d.%d.%d.%d”,ip&0xFF,(ip&0xFF00)/0x100,(ip&0xFF0000)/0x10000,(ip&0xFF000000)/0x1000000);
wsprintf(端口str,“%d”,端口);
}
}客户[最大客户];
//
sslv3(bool服务器\客户端)
{
WSADATA WSADATA;
WSAStartup(MAKEWORD(2,2)和wsaData);
c客户端=0;
fd=套接字(AF_INET、SOCK_STREAM、IPPROTO_TCP);
//
DWORD超时=1;
setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,(const char*)和timeout,sizeof(DWORD));
}
int绑定(字端口)
{
int-ret=0;
当地的sockaddr_;
local.sin_addr.s_addr=htonl(INADDR_ANY);
local.sin_family=AF_INET;
local.sin_port=htons(port);
if((ret=bind(fd,(struct sockaddr*)和local,sizeof(local)))
!=插座(U错误)
聆听(fd,索马克斯康);
返回ret;
}
int接受()
{
插座客户端fd;
客户端中的sockaddr_;
int addrlen=sizeof(客户机);
clientfd=accept(fd,(struct sockaddr*)和client,&addrlen);
如果(clientfd==-1)
返回-1;
clients[cClient].ip=client.sin\u addr.S\u un.S\u addr;
客户端[cClient].port=client.sin\u端口;
客户端[cClient].StrGen();
客户端[cClient].fd=clientfd;
客户端[cClient].Valid=true;
//
DWORD超时=1;
setsockopt(客户端[cClient].fd,SOL_套接字,SO_RCVTIMEO,(const char*)和timeout,sizeof(DWORD));
c客户端++;
如果(C客户端>=最大客户端)
{
c客户端=0;
返回最大客户端数-1;
}
返回cClient-1;
}
int Connect(字符ip[],字端口)
{
地址中的sockaddr_;
addr.sin_family=AF_INET;
addr.sin\u addr.s\u addr=inet\u addr(ip);
地址SINU port=htons(端口);
返回连接(fd,(const struct sockaddr*)&addr,sizeof(addr));
}
int发送(套接字sfd、void*缓冲区、int长度)
{
返回发送(sfd,(字符*)缓冲区,长度为0);
}
整数读取(套接字sfd、void*缓冲区、整数长度)
{
返回recv(sfd,(char*)缓冲区,长度为0);
}
};
sslv3 cssl(正确);
DWORD WINAPI读线程(void*args)
{
while(true)
{
对于(int j=0;j 0){
printf(“%s:%s说:%s\n”,cssl.clients[j].ipstr,cssl.clients[j].portstr,rpack);
}
}
}
睡眠(1);
}
返回TRUE;
}
int main()
{
cssl.Bind(1234);
CreateThread(0,0,ReadThread,0,0,0);
while(true)
{
睡眠(1);
int cid=cssl.Accept();
如果(cid!=-1){
printf(“%s:%s已连接!\n”,cssl.clients[cid].ipstr,cssl.clients[cid].portstr);
}
}
返回0;
}
以下是完整的客户端代码:

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

#include <iostream>
using namespace std;

struct sslv3
{
#define max_clients 1024
private:
    int cClient;
public:
    SOCKET fd;
    int CurrentClient()
    {
        return cClient;
    }
    struct client
    {
        client()
        {
            Valid = false;
        }
        bool Valid;
        DWORD ip;
        WORD port;
        char ipstr[33];
        char portstr[33];
        SOCKET fd;
        void StrGen()
        {
            wsprintf(ipstr, "%d.%d.%d.%d", ip & 0xFF, (ip & 0xFF00)/0x100, (ip & 0xFF0000)/0x10000, (ip & 0xFF000000)/0x1000000);
            wsprintf(portstr, "%d", port);
        }
    } clients[max_clients];
    //
    sslv3(bool server_client)
    {
        WSADATA wsaData;
        WSAStartup(MAKEWORD(2, 2), &wsaData);
        cClient = 0;
        fd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        //
        DWORD timeout = 1;
        setsockopt(fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(DWORD));
    }
    int Bind(WORD port)
    {
        int ret = 0;
        sockaddr_in local;
        local.sin_addr.s_addr = htonl(INADDR_ANY);
        local.sin_family = AF_INET;
        local.sin_port = htons(port);
        if((ret = bind(fd, (struct sockaddr *)&local, sizeof(local)))
            != SOCKET_ERROR)
            listen(fd, SOMAXCONN);
        return ret;
    }
    int Accept()
    {
        SOCKET clientfd;
        sockaddr_in client;
        int addrlen = sizeof(client);
        clientfd = accept(fd, (struct sockaddr *)&client, &addrlen);
        if(clientfd == -1)
            return -1;
        clients[cClient].ip = client.sin_addr.S_un.S_addr;
        clients[cClient].port = client.sin_port;
        clients[cClient].StrGen();
        clients[cClient].fd = clientfd; 
        clients[cClient].Valid = true;
        //
        DWORD timeout = 1;
        setsockopt(clients[cClient].fd, SOL_SOCKET, SO_RCVTIMEO, (const char*)&timeout, sizeof(DWORD));
        cClient++;
        if(cClient >= max_clients)
        {
            cClient = 0;
            return max_clients - 1;
        }
        return cClient - 1;
    }
    int Connect(char ip[], WORD port)
    {
        sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_addr.s_addr = inet_addr(ip);
        addr.sin_port = htons(port);
        return connect(fd, (const struct sockaddr*)&addr, sizeof(addr));
    }
    int Send(SOCKET sfd, void* buffer, int length)
    {
        return send(sfd, (char*)buffer, length, 0);
    }
    int Read(SOCKET sfd, void* buffer, int length)
    {
        return recv(sfd, (char*)buffer, length, 0);
    }
};

sslv3 cssl(false);

int main()
{
    cssl.Connect("127.0.0.1", 1234);
    while(true)
    {
        printf("say: ");
        char buf[1024];
        for(int i = 0; i < sizeof(buf); i++)
            buf[i] = 0;
        cin >> buf;
        int len = strlen(buf);
        cssl.Send(cssl.fd, buf, len);
    }
    return 0;
}
#包括
#包括
#pragma注释(lib,“ws2_32.lib”)
#包括
#包括
#包括
使用名称空间std;
结构sslv3
{
#定义max_客户端1024
私人:
国际客户;
公众:
插座fd;
int CurrentClient()
{
归还客户;
}
结构客户端
{
客户()
{
有效=错误;
}
布尔有效;
叶德沃德;
字端口;
char-ipstr[33];
char-portstr[33];
插座fd;
void StrGen()
{
wsprintf(ipstr,“%d.%d.%d.%d”,ip&0xFF,(ip&0xFF00)/0x100,(ip&0xFF0000)/0x10000,(ip&0xFF000000)/0x1000000);
wsprintf(端口str,“%d”,端口);
}
}客户[最大客户];
//
sslv3(bool服务器\客户端)
{
WSADATA WSADATA;
WSAStartup(MAKEWORD(2,2)和wsaData);
c客户端=0;
fd=套接字(AF_INET、SOCK_STREAM、IPPROTO_TCP);
//
DWORD超时=1;
setsockopt(fd,SOL_SOCKET,SO_RCVTIMEO,(const char*)和timeout,sizeof(DWORD));
}
int绑定(字端口)
{
int-ret=0;
当地的sockaddr_;
local.sin_addr.s_addr=htonl(INADDR_ANY);
local.sin_family=AF_INET;
local.sin_port=htons(port);
if((ret=bind(fd,(struct sockaddr*)和local,sizeof(local)))
!=插座(U错误)
聆听(fd,索马克斯康);
返回ret;
}
int接受()
{
插座客户端fd;
客户端中的sockaddr_;
int addrlen=sizeof(客户机);
clientfd=accept(fd,(struct sockaddr*)和client,&addrlen);
如果(clientfd==-1)
返回-1;
clients[cClient].ip=client.sin\u addr.S\u un.S\u addr;
客户端[cClient].port=client.sin\u端口;
客户端[cClient].StrGen();
客户端[cClient].fd=clientfd;
客户端[cClient].Valid=true;
//
DWORD超时=1;
setsockopt(客户端[cClient].fd,SOL_套接字,SO_RCVTIMEO,(const char*)和timeout,sizeof(DWORD));