LinuxSir.cn,穿越时空的Linuxsir!

 找回密码
 注册
搜索
热搜: shell linux mysql
查看: 1609|回复: 9

请教关于recv()函数的一个问题

[复制链接]
发表于 2007-4-23 16:20:38 | 显示全部楼层 |阅读模式
我写了一个client端与一个server端,但是我server端向client端发送数据的时候,server端表示已经发送出来了,但是client端却没有接收到,一直在recv()那个函数那儿阻塞着, 但是在这一个发送与接收的过程之前我的server与client端也经过了多次的数据传输都成功了的. 就是运行到当前这一个传输数据的时候出错了,不知道是什么原因? 谢谢高手们指教!
 楼主| 发表于 2007-4-23 16:20:42 | 显示全部楼层

请教关于recv()函数的一个问题

我写了一个client端与一个server端,但是我server端向client端发送数据的时候,server端表示已经发送出来了,但是client端却没有接收到,一直在recv()那个函数那儿阻塞着, 但是在这一个发送与接收的过程之前我的server与client端也经过了多次的数据传输都成功了的. 就是运行到当前这一个传输数据的时候出错了,不知道是什么原因? 谢谢高手们指教!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-23 16:24:07 | 显示全部楼层
不好意思 ,网络不好, 多发了一次
回复 支持 反对

使用道具 举报

发表于 2007-4-23 18:02:19 | 显示全部楼层
代码贴出来大家分析,注意用code标签
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-23 18:58:44 | 显示全部楼层
由于代码比较多,而且涉及到很多其它的文件操作,所以我只把有用的贴出来,望大家指教!
这是我client的代码

  1. char checkresult[3];
  2. if (send(socknum, myip, strlen(myip), 0) == -1)
  3. {
  4.         printf("error\n");
  5.         exit(1);
  6. }

  7. if ((templen = recv(socknum, checkresult, 3, 0)) == -1)
  8. {
  9.         printf("error\n");
  10.         exit(1);
  11. }

  12. while ((templen = read(filefe, buf, 100, 0)) > 0)
  13. {
  14.         write(socknum, buf, templen);
  15. }

  16. if ((templen = recv(socknum, checkresult, 3, 0)) == -1)
  17. {
  18.         printf("error\n");
  19.         exit(1);
  20. }

复制代码


这是我server端的代码

  1. char checkresult[3];
  2. if ((templen = recv(socknum, cliip, 20, 0)) == -1)
  3. {
  4.         printf("error\n");
  5.         exit(1);
  6. }

  7. strcpy(checkresult, "ok");

  8. if (send(socknum, checkresult, 3, 0) == -1)
  9. {
  10.         printf("error\n");
  11.         exit(1);
  12. }

  13. while ((templen = recv(socknum, buf, 100, 0)) > 0)
  14. {
  15.         write(filefd, buf, templen);
  16. }
  17. strcpy(checkresult, "ok");

  18. if ((templen = send(socknum, checkresult, strlen(checkresult), 0)) == -1)
  19. {
  20.         printf("error\n");
  21.         exit(1);
  22. }
复制代码


另外,在调用这些字符串的时候都进行了清为零的操作了的!
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-23 19:11:11 | 显示全部楼层
对于client与server,前面三次都可以正常地完成,但是到了最后一次server向client发送确认消息的时候,却出现了错误.
server端返回的值为2,表明已经发送了两个字节,即ok过去,但是client端却什么都接收不了.一直阻塞在recv()那个函数那个地方. 我不知道为什么会出现这种情况,前面都可以,而后面却不行!
回复 支持 反对

使用道具 举报

发表于 2007-4-23 20:09:27 | 显示全部楼层
你把精简后的client、server补充成可以编译运行,然后试试看有没有问题
另外,你设计的通讯流程是怎么样的?
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-23 21:00:11 | 显示全部楼层
这是我的server.c端

  1. #include<stdio.h>
  2. #include<sys/types.h>
  3. #include<fcntl.h>
  4. #include<string.h>
  5. #include<stdlib.h>
  6. #include<sys/socket.h>
  7. #include<netinet/in.h>
  8. #include<arpa/inet.h>
  9. #include<netdb.h>

  10. int port = 12345;

  11. int main()
  12. {
  13.         struct sockaddr_in sin;
  14.         struct sockaddr_in pin;
  15.         int socknum;
  16.         int add, fd;
  17.         int connfd;
  18.         char buf[1204];
  19.         char checkresult[3];
  20.         int i, len;
  21.         socknum = socket(AF_INET, SOCK_STREAM, 0);
  22.         if (socknum == -1)
  23.         {
  24.                 printf("call to socket\n");
  25.                 exit(1);
  26.         }

  27.         memset(&sin, 0, sizeof(sin));
  28.         sin.sin_family = AF_INET;
  29.         sin.sin_addr.s_addr = INADDR_ANY;
  30.         sin.sin_port = htons(port);
  31.         if (bind(socknum, (struct sockaddr*)&sin, sizeof(sin)) == -1)
  32.         {
  33.                 printf("call to bind\n");
  34.                 exit(1);
  35.         }

  36.         if (listen(socknum, 20) == -1)
  37.         {
  38.                 printf("listen error\n");
  39.                 exit(1);
  40.         }

  41.         printf("accetping to \n");
  42.         while (1)
  43.         {
  44.                 connfd = accept(socknum, (struct sockaddr*)&pin, &add);
  45.                 if (connfd == -1)
  46.                 {
  47.                         printf("call to accept\n");
  48.                         exit(1);
  49.                 }

  50.                 if (recv(connfd, buf, 1024, 0) == -1)
  51.                 {
  52.                         printf("call to recv\n");
  53.                         exit(1);
  54.                 }
  55.                 printf("buf = %s\n", buf);
  56.                 strcpy(checkresult, "ok");
  57.                 printf("yes\n");
  58.                 if ((i = send(connfd, checkresult, strlen(checkresult), 0)) < 1)
  59.                 {
  60.                         printf("send error\n");
  61.                         exit(1);
  62.                 }
  63.                 fd = open("recv", O_RDWR|O_CREAT, 0644);
  64.                 if (fd < 0)
  65.                 {
  66.                         printf("open error\n");
  67.                         exit(1);
  68.                 }
  69.                 while ((i = recv(connfd, buf, 100, 0)) > 0)
  70.                 {
  71.                         write(fd, buf, i);       
  72.                 }

  73.                 strcpy(checkresult, "no");

  74.                 if ((i = send(connfd, checkresult, strlen(checkresult), 0)) < 1)
  75.                 {
  76.                         printf("send error 2\n");
  77.                         exit(1);
  78.                 }

  79.                 printf("send ok\n");
  80.                 close(connfd);
  81.         }
  82.         return 0;
  83. }
  84.                
复制代码

这是我的client.c端

  1. #include<stdlib.h>
  2. #include<fcntl.h>
  3. #include<sys/types.h>
  4. #include<stdio.h>
  5. #include<string.h>
  6. #include<sys/socket.h>
  7. #include<netinet/in.h>
  8. #include<arpa/inet.h>
  9. #include<netdb.h>

  10. int port = 12345;
  11. char *hostname = "127.0.0.1";

  12. int main()
  13. {
  14.         char buf[1024];
  15.         char message[20];
  16.         int fd, i;
  17.         char checkresult[3];
  18.         int socknum;
  19.         struct sockaddr_in pin;
  20.         struct hostent *ser;
  21.         char str[20] = "A default test";
  22.         if ((ser = gethostbyname(hostname)) == 0)
  23.         {
  24.                 printf("error get host name\n");
  25.                 exit(1);
  26.         }

  27.         memset(&pin, 0, sizeof(pin));
  28.         pin.sin_family = AF_INET;
  29.         pin.sin_addr.s_addr = ((struct in_addr*)(ser->h_addr))->s_addr;
  30.         pin.sin_port = htons(port);
  31.         if ((socknum = socket(AF_INET, SOCK_STREAM, 0)) == -1)
  32.         {
  33.                 printf("call to socket\n");
  34.                 exit(1);
  35.         }

  36.         if (connect(socknum, (void*)&pin, sizeof(pin)) == -1)
  37.         {
  38.                 printf("call to connect\n");
  39.                 exit(1);
  40.         }
  41.         if ((fd = open("send", O_RDONLY)) < 0)
  42.         {
  43.                 printf("open error\n");
  44.                 exit(1);
  45.         }
  46.        
  47.         printf("send \n");
  48.         if (send(socknum, str, strlen(str), 0) == -1)
  49.         {
  50.                 printf("send error\n");
  51.                 exit(1);
  52.         }
  53.         memset(checkresult, 0, 3);
  54.         if (recv(socknum, checkresult, 3, 0) == -1)
  55.         {
  56.                 printf("recv check error\n");
  57.                 exit(1);
  58.         }
  59.         strcpy(buf, "helloworld");
  60.         printf("check = %s\n", checkresult);
  61.         memset(buf, 0, sizeof(buf));
  62.         while ((i = read(fd, buf, 100)) > 0)
  63.         {
  64.                 send(socknum, buf, i, 0);
  65.         }

  66.         memset(checkresult, 0, 3);
  67.         if (recv(socknum, checkresult, 3, 0) == -1)
  68.         {
  69.                 printf("recv error 2\n");
  70.                 exit(1);
  71.         }
  72.         printf("checkresult = %s\n", checkresult);
  73.         close(socknum);
  74.         return 0;
  75. }
  76.        
复制代码


问题就出在那个while()循环的地方,如果我不是用while()循环,而是只发送一个字符串,那么没问题,但是我使用while()的方法发送了一个文件,然后就出错了,最后server端的send函数已经成功执行,但是client端的recv()函数却始终接收不到数据而一直阻塞在那个地方!
望高手们给点帮助, 非常感谢!
回复 支持 反对

使用道具 举报

发表于 2007-4-23 23:41:51 | 显示全部楼层
我编译了你的程序,运行结果如下:
$ ./server
accetping to
call to accept
$

在server运行后启动client,在clien所在目录下预先建立了一个文件叫send
$ ./client
send
recv check error
$


建议你买一本 Unix network programing, 中文版叫unix网络编程
里面有各种服务器/客户机模式
回复 支持 反对

使用道具 举报

 楼主| 发表于 2007-4-24 08:47:17 | 显示全部楼层
Post by x11
我编译了你的程序,运行结果如下:

在server运行后启动client,在clien所在目录下预先建立了一个文件叫send


建议你买一本 Unix network programing, 中文版叫unix网络编程
里面有各种服务器/客户机模式
问题解决了, 是两个while()循环的问题, 您说的那个accept()出错的原因在于accept()的第二个参数上面, 有的地方是struct sockaddr*, 而有的地方是struct sockaddr_in*. 只不过我的机器上面的struct sockaddr*才能成功!
谢谢您的鼓励!
回复 支持 反对

使用道具 举报

您需要登录后才可以回帖 登录 | 注册

本版积分规则

快速回复 返回顶部 返回列表