首页
社区
课程
招聘
[讨论]WISOCK select 多连接问题
发表于: 2009-9-10 21:19 4163

[讨论]WISOCK select 多连接问题

2009-9-10 21:19
4163
多连接问题,单个连接已可以接收数据。
--------------------------------------------------------------
// tcpserver.cpp : Defines the entry point for the console application.
//

#include "stdafx.h"
#include <winsock2.h>
#pragma comment(lib,"ws2_32")
#include <stdio.h>
#include "string.h"

int main(int argc, char* argv[])
{      
        int  i = 0;
        int  ret;
        char revData[512]={0};
        int  listening;
        
        //sockaddr_in remoteAddr;
        //int  nAddrLen = sizeof(remoteAddr);
        //sockaddr_in remoteAddr2;
        //int  nAddrLen2 = sizeof(remoteAddr2);
        int b;
        SOCKET socka;
        
        WSADATA wsaData;
        WORD    sockVersion = MAKEWORD(2, 2);
        
        if(WSAStartup(sockVersion, &wsaData) != 0)
        return 0;
        
        SOCKET sListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
        
        if(sListen == INVALID_SOCKET)
        {
                printf("socket error\n");
                return 0;
        }
        
        u_long ul=1;
        ioctlsocket(sListen,FIONBIO,&ul);
        
        
        sockaddr_in sin;
        sin.sin_family = AF_INET;
        sin.sin_port = htons(4500);
        sin.sin_addr.S_un.S_addr = INADDR_ANY;
        
        if(bind(sListen, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
        {
                printf(" bind error \n");
                closesocket(sListen);
                return 0;
        }
        
        if((listening = listen(sListen, 5)) == SOCKET_ERROR)
        {
                printf("listen error\n");
                closesocket(sListen);
                return 0;
        }
        
        
        fd_set rfd;
        fd_set rfd2;
        FD_ZERO(&rfd);
        FD_SET(sListen,&rfd);
        
        
        select(sListen+1,&rfd,0,0,0);
        if(FD_ISSET(sListen,&rfd))
        {
                socka =accept(sListen, 0, 0);
                //sockb =accept(sListen, 0, 0);这里如此正确?有的资料这样写,但到后面将sockb 加入&rfd后select错误。
                //有个代码没用select时是先for 然后s[i] = accept(slisten,NULL,NULL); 然后开线程处理每个连接。
           //用当没有连接时,FOR完了就开了I个线程,那S[I]得到的是什么,连接如何建立?
                printf("a line\n");
               
                while(1)
                {2
                        FD_ZERO(&rfd2);
                        FD_SET(socka,&rfd2);
                        
                        if( (ret = select(0,&rfd2,0,0,0)) ==SOCKET_ERROR)
                        {
                                printf("select error\n");
                        }
                        if(ret > 0)
                        {
                                if(FD_ISSET(socka,&rfd2))
                                {
                                        memset(revData,0x00,strlen(revData));
                                        b=recv(socka,revData,512,0);
                                        if(b >0)
                                        {                                    
                                                printf("get order: %s \n",revData);
                                        }
                                       
                                }
                                
                        }
                        
                }
               
        }
        
        
        printf("all  close\n");
        gets(revData);
        closesocket(sListen);
        WSACleanup();
        
        
        return 0;
}

[注意]传递专业知识、拓宽行业人脉——看雪讲师团队等你加入!

收藏
免费 0
支持
分享
最新回复 (4)
雪    币: 254
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
2
大牛给个简单的模型吧,不用多线程方式
1、SOCKET

2 、BIND

3、LISTEN

SELECT SOCKET

4、AA = ACCEPT

SELECT AA
2009-9-10 21:35
0
雪    币: 666
活跃值: (191)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
3
// 检测TCP连接句柄 sListen  的状态。如果有客户端三次握手成功。server 收到  ack 报文。会触发 sListen 活动。
     if(FD_ISSET(sListen,&rfd))
        {
// 从 sListen 队列里捡 会话层 的活动句柄。对于每个 client 连接,server 会将他们排队。队列的大小由 listen 的第二个参数指定。
               socka =accept(sListen, 0, 0);
                //sockb =accept(sListen, 0, 0);这里如此正确?有的资料这样写,但到后面将sockb 加入&rfd后select错误。
看不懂。好像你代码里没有 sockb 啊。
                //有个代码没用select时是先for 然后s[i] = accept(slisten,NULL,NULL); 然后开线程处理每个连接。
// 当 slisten 为非阻塞句柄时, 就不需要用 select .
//用当没有连接时,FOR完了就开了I个线程,那S[I]得到的是什么,连接如何建立?s[i]得到的就是 client 的会话句柄。这个句柄用于操作应用层的数据。有一个client ,就会对应有一个 句柄。
                printf("a line\n");
2009-9-15 09:59
0
雪    币: 254
活跃值: (10)
能力值: ( LV3,RANK:20 )
在线值:
发帖
回帖
粉丝
4
改成如下,哪里有错误。还是连不上
..............      
select(sListen+1,&rfd,0,0,&timeout);
        if(FD_ISSET(sListen,&rfd))
        {        
                        for(num=0;num<5;num++)
                        {
                                                         Mysocket[i] =accept(sListen, 0, 0);
                        }

                printf("a line\n");
               
                while(1)
                {
                        FD_ZERO(&rfd2);
                        FD_SET(Mysocket[0],&rfd2);
                FD_SET(Mysocket[1],&rfd2);

                        
                        if( (ret = select(0,&rfd2,0,0,0)) ==SOCKET_ERROR)
                        {
                                printf("select error\n");
                        }
                        if(ret > 0)
                        {
                                if(FD_ISSET(Mysocket[0],&rfd2))
                                {
                                         ......有数据时读出。。
....................
2009-9-15 22:23
0
雪    币: 666
活跃值: (191)
能力值: ( LV9,RANK:190 )
在线值:
发帖
回帖
粉丝
5
这里有错误
        Mysocket[i] =accept(sListen, 0, 0);
你可以跟踪一下 Mysocket[] 的值,后四个值应该都是-1.
因为你设置了 sListen为非阻塞模式(ioctlsocket(sListen,FIONBIO,&ul))。一次cient 连接后, select 成功,第一次 accept成功。然后,后面四次 accept都会失败( 超时错误 )。随后,程序陷入 while(),一直在第一个client 连接上取数据。别的client 也就没有办法再连接。
初学者最好先学习阻塞模式。  ( 去掉ioctlsocket(sListen,FIONBIO,&ul); )这样方便理解和跟踪。
推荐资料:
关于 accept 等 socket 函数:
advanced programming in the unix environment , second edition
Chapter 16. Network IPC: Sockets
关于 select 函数:
14.5. I/O Multiplexing
2009-9-16 12:29
0
游客
登录 | 注册 方可回帖
返回
//