免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 2381 | 回复: 5

[网络] 关于SOCKET的一个巨大BUG [复制链接]

论坛徽章:
0
发表于 2013-03-20 20:03 |显示全部楼层
今天在测试EPOLL/SELECT/POLL时发现个问题,就是SELECT /EPOLL在某种情况下,返回的状态是错误,
经过再三测试,发现的确存在这样的问题,
在SELECT的时候,FD_ISSET虽然为真,但实际读取时无法读取数据,
代码如下:不信可以自己跑跑:
/*
* SocketClient.c
*
*  Created on: 2013-3-19
*      Author: root
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/io.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <bits/socket.h>
#include <sys/ioctl.h>
#include <fcntl.h>
int main()
{

        int i=0;
        struct sockaddr_in sockServer;
        sockServer.sin_addr.s_addr=inet_addr("192.168.8.198");
        sockServer.sin_port = 10008;
        sockServer.sin_family=AF_INET;
        char buff[1024];
        memset(buff,1,1024);
        int iServer=0;
        time_t befTime=time(NULL);
        pid_t pid=0;
        //int flag= fcntl(iClient,F_GETFL,0);
        //printf("NONBLOCK :%d\n",flag & O_NONBLOCK);
        for(i=0; i<900; i++)
        {
                pid=fork();
                if(pid == 0)
                {

                        int iClient= socket(AF_INET,SOCK_STREAM,0);
                        printf("Process %d Socket :%d \n",i,iClient);
                        int iW=connect(iClient,(struct sockaddr*)&sockServer,sizeof(struct sockaddr_in));
                        printf("Process %d Connect Result:%d  Error: %d\n",i,iW,errno);
                        iW=write(iClient,buff,1024);
                        printf("Process %d  Write Result: %d \n",i,iW);
                        //_exit(0);
                        //pause();
                        return 0;
                }
        }

        int times=0;
        while(times<900)
        {
                wait(NULL);
                times++;
        }
        time_t endTime=time(NULL);
        printf("Over ,Total Time :%d \n",endTime-befTime);
        exit(0);
}



/*
============================================================================
Name        : TestFork.c
Author      : Lixianke
Version     :
Copyright   : Jetsen
Description : Hello World in C, Ansi-style
============================================================================
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <sys/io.h>
#include <fcntl.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#include <bits/socket.h>
#define max(a,b) (a>b ? a: b)
typedef enum {false = 0, true = 1} bool;
int main(void) {

        int iServer= socket(AF_INET,SOCK_STREAM,0);
        struct sockaddr_in iAddr;
        iAddr.sin_addr.s_addr =INADDR_ANY;//inet_addr("");
        iAddr.sin_port=10008;
        iAddr.sin_family=AF_INET;
        int iRe=bind(iServer,(struct sockaddr*)&iAddr,sizeof(struct sockaddr_in));
        printf("Bind Server %d ,Error: %d\n",iRe,errno);

        iRe=listen(iServer,1024);
        printf("Listen Server %d \n",iRe);

        int pClient[1024];
        int iIndex =1,iMax=0;
        char buff[1024];
        time_t befTime=time(NULL);
        printf("Server Start,Socket %d \n",iServer);
        int iFlag=fcntl(iServer,F_GETFL,0);
        printf("Block: %d \n",iFlag & O_NONBLOCK);
        while(true)
        {
                fd_set readSet;
                FD_ZERO(&readSet);
                FD_SET(iServer,&readSet);
                pClient[0] = iServer;
                int i=1;
                for(; i< iIndex; i++)
                {
                        FD_SET(pClient[i],&readSet);
                        iMax = max(pClient[i],iMax);
                }

                iMax = max(iServer,iMax);

                select(iMax+1,&readSet,NULL,NULL,NULL);
                for (i = 1; i < iIndex; i++)
                {
                        if (pClient[i] != iServer && FD_ISSET(pClient[i],&readSet))
                        {
                                int j=read(pClient[i], buff, 1024);
                                printf("Server %d Read %d Fileno %d ,Ret ,%d\n ",i,j,pClient[i],FD_ISSET(pClient[i],&readSet));
                        }
                }
                if(FD_ISSET(iServer,&readSet))
                {
                        pClient[iIndex]=accept(iServer,NULL,NULL);
                        printf("Server Accept %d \n",iIndex);
                        ++iIndex;
                }
        }
        time_t endTime=time(NULL);
        printf("Over ,Total Time :%d \n",endTime-befTime);
        return EXIT_SUCCESS;
}

论坛徽章:
0
发表于 2013-03-20 20:03 |显示全部楼层
Server 619 Read 0 Fileno 622 ,Ret ,1
Server 620 Read 0 Fileno 623 ,Ret ,1
Server 621 Read 0 Fileno 624 ,Ret ,1
Server 622 Read 0 Fileno 625 ,Ret ,1
Server 623 Read 0 Fileno 626 ,Ret ,1
Server 624 Read 0 Fileno 627 ,Ret ,1
Server 625 Read 0 Fileno 628 ,Ret ,1
Server 626 Read 0 Fileno 629 ,Ret ,1
Server 627 Read 0 Fileno 630 ,Ret ,1
Server 628 Read 0 Fileno 631 ,Ret ,1
Server 629 Read 0 Fileno 632 ,Ret ,1
Server 630 Read 0 Fileno 633 ,Ret ,1
Server 631 Read 0 Fileno 634 ,Ret ,1
这是部分测试结果:
Server 632 Read 0 Fileno 635 ,Ret ,1
Server 633 Read 0 Fileno 636 ,Ret ,1
Server 634 Read 0 Fileno 637 ,Ret ,1
Server 635 Read 0 Fileno 638 ,Ret ,1
Server 636 Read 0 Fileno 639 ,Ret ,1
Server 637 Read 0 Fileno 640 ,Ret ,1
Server 638 Read 0 Fileno 641 ,Ret ,1
Server 639 Read 0 Fileno 642 ,Ret ,1
Server 640 Read 0 Fileno 643 ,Ret ,1

论坛徽章:
0
发表于 2013-03-20 20:21 |显示全部楼层
服务器的TCP监听结果:
tcp        0      0 192.168.8.198:6183          192.168.11.46:52598         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52085         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51829         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52597         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52341         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51828         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52084         CLOSE_WAIT  
tcp     1025      0 192.168.8.198:6183          192.168.11.46:52091         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51835         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52346         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51834         CLOSE_WAIT  
tcp     1025      0 192.168.8.198:6183          192.168.11.46:52090         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51833         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51832         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52088         CLOSE_WAIT  
tcp     1025      0 192.168.8.198:6183          192.168.11.46:52095         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51839         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51838         CLOSE_WAIT  
tcp     1025      0 192.168.8.198:6183          192.168.11.46:52094         CLOSE_WAIT  
tcp     1025      0 192.168.8.198:6183          192.168.11.46:52093         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51837         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51836         CLOSE_WAIT  
tcp     1025      0 192.168.8.198:6183          192.168.11.46:52348         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52067         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51811         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51810         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52066         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52065         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51809         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52576         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51808         CLOSE_WAIT  
tcp     1025      0 192.168.8.198:6183          192.168.11.46:52064         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:52071         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51815         CLOSE_WAIT  
tcp        0      0 192.168.8.198:6183          192.168.11.46:51814         CLOSE_WAIT  

论坛徽章:
0
发表于 2013-03-20 20:22 |显示全部楼层
在客户端有多个进程进行连接到服务器同一端口时,服务器会采用最后一个SOCKET连接做数据收发,但是建立1对多的SOCKET连接,,这是个漏洞。

论坛徽章:
7
天蝎座
日期:2013-09-28 10:45:42双子座
日期:2013-10-16 16:27:09射手座
日期:2013-10-23 10:21:32处女座
日期:2014-09-17 16:44:332015年亚洲杯之巴林
日期:2015-04-09 17:28:01冥斗士
日期:2015-11-26 16:19:0015-16赛季CBA联赛之山东
日期:2018-03-02 23:59:31
发表于 2013-03-21 11:57 |显示全部楼层
本帖最后由 cxytz01 于 2013-03-21 12:04 编辑

回复 1# slata

1.为什么read放在accpet之前?
2.iAddr.sin_port=10008;  为什么端口是这么赋值的? 是懒得写,还是真的写错了?
3.为什么客户端要绑定端口,如果客户端和服务端都在一台机器上,会不会因为绑定的端口相同而出问题?


为什么要把accept的fd给放到readfd_set里面? 这么放的话,select是会监听accpet动作的,一旦客户发生connect请求,拥有accept fd的fd_set就活动了,select就成功返回,然后read当然是0。

论坛徽章:
0
发表于 2014-02-17 15:14 |显示全部楼层
SELECT  ACCEPT SOCKET是正常的。
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

北京盛拓优讯信息技术有限公司. 版权所有 京ICP备16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122 niuxiaotong@pcpop.com 17352615567
未成年举报专区
中国互联网协会会员  联系我们:huangweiwei@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP