首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > C++ >

为何大量Socket并发请求时会有部分失败? 求高手解答!

2013-04-21 
为什么大量Socket并发请求时会有部分失败??求高手解答!!现象:同时启动2000个线程,每个线程都去访问同一个

为什么大量Socket并发请求时会有部分失败?? 求高手解答!!
现象:
  同时启动2000个线程,每个线程都去访问同一个服务器(IP、端口相同)。
  发现会有部分线程连接失败,错误码一般有下面两个:
  ①10048(Address already in use.)
  ②10061(Connection refused.) 

  另:不同的服务器出错的比率也不同,自己写的Java服务端出错的比率要比Apache的多(服务端只把客户端发来的字符串打印到屏幕上,然后继续接收下一个请求)。

问题:
  为什么在很短的时间内有过多的网络连接请求时,会有部分连接失败?其根本原因是什么?(1024-5000内的端口还有剩余)
  Java/C/C++、Windows/Linux都有同样的问题,所以应该是Socket或底层网络设备或驱动的问题,不过没找到权威的资料。

  如能给几个参考文档也是极好的~

  注:请不要回答如何规避这个问题的方法,公司要我调查出现这个问题的原因。调查好久了没找到答案、只好发帖求助了。

代码:
下面是客户端代码,服务端的很简单就不贴出来了,访问www.baidu.com 或本地Apache服务都是一样的问题。


// main 函数
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
// Win Socket初始化
    // ...

    // 创建2000个线程
    HANDLE  ths[2000] = {0};
    for(int i=0; i<2000; i++) {
        HANDLE hTh = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ThreadProc, 
        (LPVOID)(i+1), CREATE_SUSPENDED, NULL);
        if(NULL == hTh) {
            printf("Create thread failed(%d:%d)\n", i, GetLastError());
            return -1;
        }
        ths[i] = hTh;
    }
    printf("Create thread success.\n");
    
    // 启动创建好的线程
    for(int i=0; i<2000; i++) {
        ResumeThread(g_th[i]);
    }

    Sleep(5000);
return nRetCode;
}


// 线程函数
DWORD ThreadProc(LPVOID lpParameter)
{
    char ch[100] = {0};
    int i = (int)lpParameter;
    
    SOCKET sockClient=socket(AF_INET,SOCK_STREAM,0);
    if (INVALID_SOCKET == sockClient) {
        printf("socket error(%d:%d)\n", i, WSAGetLastError());
        return 1;
    }

    SOCKADDR_IN addrSrv;
    addrSrv.sin_addr.S_un.S_addr=inet_addr("localhost");
    addrSrv.sin_family=AF_INET;
    addrSrv.sin_port=htons(80);
    int err = connect(sockClient, (SOCKADDR*)&addrSrv, sizeof(SOCKADDR));
    if(SOCKET_ERROR == err) {
    // 会出现10048、10061两种类型的错误
        printf("connect error(%d:%d)\n", i, WSAGetLastError());
        return 1;
    }

    sprintf(ch, "GET /app/?a=%d HTTP/1.1", i);
    err = send(sockClient, ch, strlen(ch)+1, 0);
    if(SOCKET_ERROR == err) {
        printf("send error(%d:%d)\n", i, WSAGetLastError());


        return 1;
    }
    closesocket(sockClient);

    printf("proc ok(%d)\n", i);
    return 0;
}


socket 服务器
[解决办法]
10048(Address already in use.):
目测是connect的频率太快,每一个socket在调用closesocket进行关闭操作后,虽然closesocket执行完毕,但是对应的占用端口并不是立即释放,这些端口需要继续处于占用状态,等待时间大约2ML(数据包最大生存周期),默认最大值为4分钟。用netstat命令查看端口状态,端口显示TIME_WAIT,在4分钟内如果对同一个端口进行connect,就会10048。

10061(Connection refused.):
目测是connect的频率太快,服务器拒绝了该连接,服务器的listen(SOCKET s, int backlog),
backlog就是等待连接队列的最大长度。比如服务器设置的是10,你同时有11个客户端连接请求,那么最后一个连接就会10061

热点排行