免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
12下一页
最近访问板块 发新帖
查看: 3694 | 回复: 11
打印 上一主题 下一主题

[C] select实现的回射服务器 [复制链接]

论坛徽章:
0
跳转到指定楼层
1 [收藏(0)] [报告]
发表于 2009-04-24 11:05 |只看该作者 |倒序浏览
找了一圈,觉得发在这个版块最合适。
我按照unix网络编程中的步骤以select实现了一个回射服务器,可是当只有一个连接的时候,正常工作,当第二个以上的连接连入时,客户端输入时,会阻塞在select函数,这时在第一个客户输入时,第二个客户的输入才会从服务器回射,不知道为什么,请高手指导。

下面是服务器和客户端的代码,运行时,注意修改IP.


serv.c

#define SERV_PORT 9877
#include "sys/select.h"
#include "sys/socket.h"
#include "netinet/in.h"
#include "string.h"
#include "stdio.h"
int main()
{
        int skt = socket(AF_INET,SOCK_STREAM,0);
        struct sockaddr_in servaddr;
        servaddr.sin_port = htons(SERV_PORT);
        servaddr.sin_family = AF_INET;
        inet_pton(AF_INET,"192.168.85.128",&servaddr.sin_addr);
        bind(skt,(struct sockaddr*)&servaddr,sizeof(servaddr));
        listen(skt,1024);
        int client[FD_SETSIZE],i;
        for(i=0;i<FD_SETSIZE;++i)
                client = -1;
        fd_set set,allset;
        FD_ZERO(&allset);
        FD_SET(skt,&allset);
        int stdeof = 0;
        int maxfd = skt ;
        int maxi = -1;

        for(;;)
        {
                set=allset;
                int nready = select(maxfd+1,&set,NULL,NULL,NULL);
                if(FD_ISSET(skt,&set))
                {
                        int connfd = accept(skt,NULL,NULL);
                        printf("new connectio:%d\n",connfd);
                        for(i=0;i<FD_SETSIZE;++i)
                                if(client<0)
                                {
                                        client = connfd;
                                        break;
                                }
                        FD_SET(connfd,&allset);
                        if(connfd > maxfd )
                                maxfd = connfd;
                        if( i>maxi )
                                maxi = i;
                        if(--nready<=0)
                                continue;
                }
                for(i=0;i<=maxi;++i)
                {
                        if(client<0)
                                continue;
                        if(FD_ISSET(client,&set))
                        {
                                int n;
                                char line[10240];
                                if((n=read(client,line,sizeof(line))) == 0)
                                {
                                        close(client);
                                        FD_CLR(client,&allset);
                                        client = -1;
                                }
                                else
                                        write(client,line,strlen(line));
                        }
                        if(--nready<=0)
                                break;
                }
        }
}


client.c

#include "sys/socket.h"
#include "netinet/in.h"
#include "stdio.h"
#include "string.h"
int main(int argc,char* argv[])
{
        if(argc!=2)
        {
                printf("命令名+IP\n");
                return 1;
        }
        int skt = socket(AF_INET,SOCK_STREAM,0);
        if(skt == -1)
        {
                printf("socket error.\n");
                return 1;
        }
        struct sockaddr_in servaddr;
        servaddr.sin_port = htons(9877);
        servaddr.sin_family = AF_INET;
        inet_pton(AF_INET,argv[1],&servaddr.sin_addr);
        int ret=connect(skt,(struct sockaddr*)&servaddr,sizeof(servaddr));
        if(ret == -1)
        {
                printf("connect error.\n");
                return 1;
        }
        char line[1024],recv[1024];
        while(scanf("%s",line)!=EOF)
        {
                write(skt,line,strlen(line));
                int n= read(skt,recv,sizeof(recv));
                recv[n] = 0;
                printf("%s\n",recv);
        }
       
}

论坛徽章:
0
2 [报告]
发表于 2009-04-24 11:22 |只看该作者
>>当第二个以上的连接连入时,客户端输入时,会阻塞在select函数

这是因为你传给select的timeout参数是NULL,man select可知:
If timeout is NULL (no timeout), select() can block indefinitely.

因此只有当client有输入时,select才会返回.

论坛徽章:
0
3 [报告]
发表于 2009-04-24 11:28 |只看该作者
第二个客户我也有输入啊,然后按了回车,这时服务器上第二个客户的已连接套接口就会准备好啊,不知道这样理解对不对?
但实际情况是我在第二个客户上输入了,也按了回车,还是没有反应。
这时再在第一个客户上输入,第二个客户的才会回射回来。

论坛徽章:
0
4 [报告]
发表于 2009-04-24 11:32 |只看该作者
你这个代码可以编译过去?

if(client<0)
                                {
                                        client = connfd;
                                        break;
                                }


client是一个int数组

论坛徽章:
0
5 [报告]
发表于 2009-04-24 11:36 |只看该作者
可以啊。这个应该关系不大吧,实际上都是整数,书上也是写的int.难道跟这个有关?

论坛徽章:
324
射手座
日期:2013-08-23 12:04:38射手座
日期:2013-08-23 16:18:12未羊
日期:2013-08-30 14:33:15水瓶座
日期:2013-09-02 16:44:31摩羯座
日期:2013-09-25 09:33:52双子座
日期:2013-09-26 12:21:10金牛座
日期:2013-10-14 09:08:49申猴
日期:2013-10-16 13:09:43子鼠
日期:2013-10-17 23:23:19射手座
日期:2013-10-18 13:00:27金牛座
日期:2013-10-18 15:47:57午马
日期:2013-10-18 21:43:38
6 [报告]
发表于 2009-04-24 11:37 |只看该作者
原帖由 converse 于 2009-4-24 11:32 发表
你这个代码可以编译过去?

if(client


Smilies搞的鬼,字都成斜体了

论坛徽章:
0
7 [报告]
发表于 2009-04-24 11:38 |只看该作者
我开了两个客户,建立了两个连接,应该是正常的吧。

tcp        2      0 192.168.85.128:9877         192.168.85.128:55242        ESTABLISHED
tcp        0      0 192.168.85.128:9877         192.168.85.128:55241        ESTABLISHED

论坛徽章:
0
8 [报告]
发表于 2009-04-24 12:52 |只看该作者
问题发现了:

照着下面这部分将对应的代码改过来就是了,至于为什么,你自己去想想吧


  1. for(i=0;i<=maxi;++i)
  2.             {   
  3.                 if(client[i]<0)
  4.                     continue;
  5.                 if(FD_ISSET(client[i],&set))
  6.                 {   
  7.                     int n;
  8.                     char line[10240];
  9.                     if((n=read(client[i],line,sizeof(line))) == 0)
  10.                     {   
  11.                         close(client[i]);
  12.                         FD_CLR(client[i],&allset);
  13.                         client[i] = -1;
  14.                     }   
  15.                     else
  16.                     {   
  17.                         printf("read from %d: %s\n", client[i], line);
  18.                         write(client[i],line,strlen(line));
  19.                         memset(line, 0, sizeof(line));
  20.                     }   
  21.                     if(--nready<=0)
  22.                         break;
  23.                 }   
  24.             }   
复制代码

论坛徽章:
0
9 [报告]
发表于 2009-04-24 12:53 |只看该作者
另外,select实际上没有阻塞,不信你top看看你的程序实际上CPU占用率是100%,也就是死循环了.

论坛徽章:
5
2015年辞旧岁徽章
日期:2015-03-03 16:54:152015年迎新春徽章
日期:2015-03-04 09:53:172015亚冠之水原三星
日期:2015-06-02 16:34:202015年亚冠纪念徽章
日期:2015-10-19 18:13:37程序设计版块每日发帖之星
日期:2015-11-08 06:20:00
10 [报告]
发表于 2009-04-24 13:04 |只看该作者
原帖由 cgp2001 于 2009-4-24 11:38 发表
我开了两个客户,建立了两个连接,应该是正常的吧。

tcp        2      0 192.168.85.128:9877         192.168.85.128:55242        ESTABLISHED
tcp        0      0 192.168.85.128:9877         192.1 ...


非阻塞的套接字上,服务器端不用accept()也能ESTABLISHED,只不过用 netstat -anp 看不到进程名

accept()前
tcp  0  0 192.168.1.***:80  192.168.1.***:20393  ESTABLISHED -

accept()后
tcp  0  0 192.168.1.***:80  192.168.1.***:20394  ESTABLISHED 4007/Httpd

[ 本帖最后由 xinglp 于 2009-4-24 13:05 编辑 ]
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

  

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

清除 Cookies - ChinaUnix - Archiver - WAP - TOP