tcp 使用select 管理客户端

(>^ω^<)喵上树 2014-06-19 02:51:31
想通过select函数管理客户端是否有数据传来。
帮忙看下这个用法有什么问题????





typedef struct _t_client
{
int fd;
struct sockaddr_in addr;
}tClient;


//用户集合
tClient client[FD_SETSIZE];

int Init_tcp_server();

int process_data(tClient * pClient);

int main()
{
int i = 0;
for(i = 0; i < FD_SETSIZE; i++)
{
client[i].fd = -1;
memset(&client[i].addr, 0, sizeof(struct sockaddr_in));
}

Init_tcp_server();
}


int Init_tcp_server()
{
int i = 0;
int sockfd = 0;
int listenfd = 0;
int connectfd = 0;
int maxi = 0;
int maxfd = 0;
fd_set rset, allset;
socket_len sin_size = 0;
int nready = 0;
int recv_byte = 0;
char recvbuf[1024] = {0};
char temp[32] = {0};
struct sockaddr_in svraddr;
struct sockaddr_in cliaddr;
struct timeval wait;

sin_size = sizeof(struct sockaddr_in);

listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd < 0)
{
perror("Create tcp socket fail!");
exit(1);
}

memset(&svraddr, 0, sizeof(struct sockaddr_in));
svraddr.sin_family = AF_INET;
svraddr.sin_port = htons(4321);
svraddr.sin_addr.s_addr = INADDR_ANY;

if(bind(listenfd, (struct sockaddr *)&svraddr, sizeof(svraddr) == -1)
{
perror("Bind fail!");
close(listenfd);
exit(1);
}

if(listen(listenfd, 5) == -1)
{
perror("Listen fail!");
close(listenfd);
exit(1);
}

maxfd = listenfd;

FD_ZERO(&allset);
FD_SET(listenfd, &allset);

while(1)
{
wait.tv_sec = 5;
wait.tv_usec = 0;
rset = allset;
if(FD_ISSET(listenfd, &allset))
{
memset(cliaddr, 0, sizeof(struct sockaddr_in));
if( (connectfd = connect(listenfd, (struct sockaddr *)&cliaddr, &sin_size)) == -1 )
{
perror("Connect fail!");
continue;
}


inet_ntop(AF_INET, &cliaddr.sin_addr, temp, 32);
printf(" [%s] [%d] connected!\n", temp, ntohs(cliaddr.sin_port));
for(i = 0; i < FD_SETSIZE; i++)
{
if(client[i].fd < 0)
{
client[i].fd= connectfd;
client[i].addr = cliaddr;
}
}

FD_SET(connectfd, &allset);
if(connectfd > maxfd) maxfd = connectfd;
if(i > maxi) maxi = i;
}


for(i = 0; i <= maxi; i++)
{
nready = select(FD_SETSIZE, &rset, NULL, NULL, &wait);
/* select函数这么 使用合理吗? 将 listenfd 也加入了 FD_SET集合。
它是处于什么状态的。。*/
if(--nready <= 0)
{
break; //FD_SET 集合中没有可读的socket描述符
}
else
{
if((sockfd = client[i].fd) < 0) continue;

recv_byte = recv(sockfd, recvbuf, 1024, 0);

if(recv_byte < 0)
{
//.....
}
else if(recv_byte == 0)
{
//....
}
else
{
process_data(&client[i]);
}
}
}
}
close(listenfd);


}


int process_data(tClient * pClient)
{
//...
}



...全文
146 4 打赏 收藏 转发到动态 举报
写回复
用AI写文章
4 条回复
切换为时间正序
请发表友善的回复…
发表回复
(>^ω^<)喵上树 2014-06-20
  • 打赏
  • 举报
回复
看下思路是这样的吗??


///////////////////////////////////////////////////////////////////////////
/*          建立一个IPV4服务器, 可以接受  V4和v6 客户端的请求*/
struct sockaddr_in  saddr;
struct sockaddr_in  caddr_v4;
struct sockaddr_in6 caddr_v6;
unsigned int ipaddr[4] = {0};
ipaddr[2] = 0xffff0000;

sockfd = socket(AF_INET, SOCK_DGRAM, 0);

saddr.sin_family = AF_INET;
saddr.sin_port = htons(4321);
saddr.sin_addr_s_addr = INADDR_ANY;

bind(sockfd, (struct sockaddr *)&saddr, sizeof(saddr));


while(1)
{
    sin_size = sizeof(caddr_v6);
    len = recvform(sockfd, rbuff, sizeof(rbuff), 0, (struct sockaddr *)caddr_v6, &sin_size);

    if(len >0)
    {
        if( memcmp(ipaddr,caddr_v6.sin6_addr.s6_addr32,12) == 0)  // ipv4
        {
            caddr_v4.sin_family = AF_INET;
            caddr_v4.sin_port = caddr_v6.sin6_port;
            caddr_v4.sin_addr.s_addr = caddr_v6.sin6_addr.s6_addr32[3];
            
            //...
        }
        else
        {
            //...
        }
    }
}
//////////////////////////////////////////////
/*       建立一个IPV6服务器,只能接收v6 客户端的请求  */
struct sockaddr_in6 saddr_v6;
struct sockaddr_in6 caddr_v6;

sockfd = socket(AF_INET6, SOCK_DGRAM, 0);

saddr.sin6_family = AF_INET6;
saddr.sin6_port = htons(4321);
saddr.sin6_addr = in6addr_any;

bind(sockfd, (struct sockaddr *)&saddr_v6, sizeof(saddr_v6));

while(1)
{
    sin_size = sizeof(caddr_v6);
    len = recvform(sockfd, rbuff, sizeof(rbuff), 0, (struct sockaddr *)caddr_v6, &sin_size);

    if(len >0)
    {
        //...
    }
}
(>^ω^<)喵上树 2014-06-20
  • 打赏
  • 举报
回复
创建一个 tcp socket 服务器 IPv4

  sockfd = socket(AF_INET, SOCK_STREAM ,0);
他是不是能接收IPv4 和 IPv6类型客户端的连接请求? 创建一个TCP SOCKET 服务器 IPv6

  sockfd = socket(AF_INET6, SOCK_STREAM, 0)
他是不是只能接收 IPv6类型客户端的连接请求?
(>^ω^<)喵上树 2014-06-19
  • 打赏
  • 举报
回复
引用 1 楼 fishion 的回复:
有listen又有connect。。你这到底是server端还是client端了
额, 这里写错了,,是 accept。。失误。没有编译!!!!
fishion 2014-06-19
  • 打赏
  • 举报
回复
有listen又有connect。。你这到底是server端还是client端了

69,382

社区成员

发帖
与我相关
我的任务
社区描述
C语言相关问题讨论
社区管理员
  • C语言
  • 花神庙码农
  • 架构师李肯
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧