Chinaunix

标题: 关于套接字的recv函数 ---急 [打印本页]

作者: DNS_WXC    时间: 2008-01-22 16:08
标题: 关于套接字的recv函数 ---急
写了一个客户端与服务器端的程序,发现有问题:
服务器端通过send函数将数据发送给客户端的时候,没有问题,存储在sendbuf缓冲区内:
"Linux", '\0' <repeats 15 times>, "34\000\000FreeBSD", '\0' <repeats 13 times>,
"67\000\000Helo", '\0' <repeats 16 times>, "45", '\0' <repeats 29 times>
以上即为发送的缓冲区的数据。
但是客户端通过套接字函数recv进行接收时,却只接受了“Linux”,请教一下:
如何才能把数据完全读过来??
谢谢!!!求救!!
作者: dotnetdotcn    时间: 2008-01-22 16:11
你在客户端用PRINTF打印的?printf遇\0就停了,是不是已经接收到了你没有发现,用GCC调试一下看看
作者: anthony1983    时间: 2008-01-22 16:14
通信协议不指定消息长度是缺乏常识性的做法
作者: scutan    时间: 2008-01-22 16:16
原帖由 anthony1983 于 2008-1-22 16:14 发表
通信协议不指定消息长度是缺乏常识性的做法


我初学网络编程的时候也是搞不懂这个问题.

建议楼主对于应用层的协议好好考虑一下, 一般简单的情况下就是先发送此次传送的数据大小, 然后再发送. 而接收方也是, 先接收此次接收数据的大小, 然后再接收这些多的字节数.
作者: DNS_WXC    时间: 2008-01-22 16:22
"Linux\000\000\000[\000B鋓\000B\024\n\023B潸?磕??緿??坷糪000@\177\003\000\000\001\000\000\000P?aB\177\200\000@,X\001@]\000\000\0008Z\001@\200??縗003綷000@訹\001@\200c\001@\001\000\000\000\000\000\000\000\201T\001B闬204\004\b鳿016\023B"
这是recvbuf的内容。可以发现没有接受到。
下面是我客户端接收数据的程序:
if ((numbytes=recv(fd,recvbuf,MAXDATASIZE,0)) == -1){
                perror("recv( ) failed!!\n");
                exit(1);
                }
        recvbuf[numbytes]='\0';
        printf("TCP Server Message:%s\n",recvbuf);
作者: DNS_WXC    时间: 2008-01-22 16:29
不知scutan可否讲的稍微详细一点??
学习学习!!!
作者: scutan    时间: 2008-01-22 16:35
原帖由 DNS_WXC 于 2008-1-22 16:29 发表
不知scutan可否讲的稍微详细一点??
学习学习!!!


我也没编过很大的程序, 都是自己写了耍的.
在发送端的话:

  1. char buf[] = "hello world";
  2. int count = strlen(buf);
  3. if (send(sockfd, &count , sizeof(int), 0) != sizeof(int))
  4. {
  5. }
  6. if (send(sockfd, buf, count, 0) != count)
  7. {
  8. }
复制代码

在接收端:

  1. char *buf;
  2. int count;
  3. if ((n = recv(sockfd, &count, sizeof(int), MSG_WAITALL)) != sizeof(int))
  4. {
  5. }
  6. buf = (char *)malloc(count+1);
  7. if (buf == NULL)
  8. {
  9. }
  10. if ((n = recv(sockfd, buf, count, MSG_WAITALL)) != count)
  11. {
  12. }
复制代码

作者: DNS_WXC    时间: 2008-01-22 16:51
刚才看到scutan提供的简单架构,测试了一下,
j=send(connectfd,sendbuf,strlen(sendbuf),0);
发现原来send的返回值j是5。也就意味着只是发送了一个“Linux”数据,
那如何实现呢?
是不是在发送方与接受方都要不停的循环使用send与recv?
作者: DNS_WXC    时间: 2008-01-22 18:30
问题已经解决...
原来是发送方调用时,改为以下的
j=send(connectfd,sendbuf,sizeof(sendbuf),0);即可
问题虽小,却能影响效率。。就是数据传输时的长度一定要搞定!!
只需将
strlen(sendbuf)改为sizeof(sendbuf)即可!!
再次感谢各位的帮忙!!
作者: flw    时间: 2008-01-22 18:32
再一次强调“语义”
作者: ivhb    时间: 2008-01-22 18:33
不要用这么专业的词嘛
直接说,好好的man手册
作者: flw    时间: 2008-01-22 18:37
原帖由 ivhb 于 2008-1-22 18:33 发表
不要用这么专业的词嘛
直接说,好好的man手册

man 手册查不出来这些的。
好比 printf( "........: %s\n", recvbuf ); 你能 man 出哪儿错了吗?
作者: scutan    时间: 2008-01-22 18:45
原帖由 flw 于 2008-1-22 18:32 发表
再一次强调“语义”


我明白你的意思.
楼主的程序虽然已经成功了, 但是对于strlen, sizeof却有点混淆.
作者: JohnBull    时间: 2008-01-22 20:18
原帖由 anthony1983 于 2008-1-22 16:14 发表
通信协议不指定消息长度是缺乏常识性的做法


我的观点:
在流式套接字上,用RFC822风格进行通信,从来不指定长度。 并且认为在流式套接字上指定信息长度弊大于利。
在(基于UDP的)数据报套接字上,指定长度纯属多余。


所以:基于TCP/IP设计的用户层协议使用二进制的长度字段纯属多余。

[ 本帖最后由 JohnBull 于 2008-1-22 20:19 编辑 ]
作者: flw    时间: 2008-01-22 20:21
原帖由 JohnBull 于 2008-1-22 20:18 发表


我的观点:
在流式套接字上,用RFC822风格进行通信,从来不指定长度。 并且认为在流式套接字上指定信息长度弊大于利。
在(基于UDP的)数据报套接字上,指定长度纯属多余。


所以:基于TCP/IP ...

太偏激了,而且你以前不这样,后来不知什么时候才有了这个观点。
作者: cugb_cat    时间: 2008-01-22 20:24
标题: 回复 #14 JohnBull 的帖子
我先看看RFC822的内容去~~~
作者: JohnBull    时间: 2008-01-22 20:31
原帖由 flw 于 2008-1-22 20:21 发表

太偏激了,而且你以前不这样,后来不知什么时候才有了这个观点。



我故意的,有戏剧效果,意在挑起论战。

BTW:我写程序确实基本上不使用固定的长度字段
作者: JohnBull    时间: 2008-01-22 20:32
原帖由 cugb_cat 于 2008-1-22 20:24 发表
我先看看RFC822的内容去~~~


不用看了,用嗅探器看看HTTP的头部就行了。
http头部设计就是rfc822风格的。
作者: flw    时间: 2008-01-22 20:33
原帖由 JohnBull 于 2008-1-22 20:31 发表

BTW:我写程序确实基本上不使用固定的长度字段

一共写过弎程序,一个用了,两个没用?
作者: JohnBull    时间: 2008-01-22 20:37
原帖由 flw 于 2008-1-22 20:33 发表

一共写过弎程序,一个用了,两个没用?


一个一个说吧:
首先:UDP套接字不必使用长度字段,对不对?
作者: cugb_cat    时间: 2008-01-22 20:40
标题: 回复 #18 JohnBull 的帖子
我不用长度,用标志也行,不过还是觉得长度好用啊。
作者: JohnBull    时间: 2008-01-22 20:47
原帖由 cugb_cat 于 2008-1-22 20:40 发表
我不用长度,用标志也行,不过还是觉得长度好用啊。


关键是用什么标志。

流式套接字上设计协议,最省事的办法是使用文本通讯,以回车为标志。(参看http)

当以回车为标志的时候,你觉得还麻烦吗?
man getline
man fgets


而且你同时回避了诸如“字节序”、“对齐”等若干极易导致BUG的陷阱......
作者: flw    时间: 2008-01-22 20:48
原帖由 JohnBull 于 2008-1-22 20:37 发表

一个一个说吧:
首先:UDP套接字不必使用长度字段,对不对?

其次,不想和你讨论这个问题。

作者: flw    时间: 2008-01-22 20:48
原帖由 JohnBull 于 2008-1-22 20:47 发表

man getline
man fgets

man lex
man yacc
作者: JohnBull    时间: 2008-01-22 20:52
原帖由 flw 于 2008-1-22 20:48 发表

其次,不想和你讨论这个问题。


UDP数据报的情况本来就不用讨论!
就说“是”还是“不是”就行了。
作者: flw    时间: 2008-01-22 20:53
原帖由 JohnBull 于 2008-1-22 20:52 发表

UDP数据报的情况本来就不用讨论!
就说“是”还是“不是”就行了。

理论上来讲,只让对方回答“是”还是“不是”可以得到任何自己想要的结果。

作者: JohnBull    时间: 2008-01-22 20:55
原帖由 flw 于 2008-1-22 20:48 发表

man lex
man yacc


我们的实现方案应该是简化编程,而不是繁化。

如果对于某种复杂协议,使用les/yacc能够简化设计,为什么不用呢?
而对于多数简单协议,使用fgets/strsep就能解决,为什么要动用lex/yacc呢?

作者: cugb_cat    时间: 2008-01-22 20:57
恩,基于文本的协议还是不要长度的好点,不过诸如传文件之类的,不要长度就不好说了吧。
作者: cugb_cat    时间: 2008-01-22 20:57
标题: 回复 #27 JohnBull 的帖子

不错
作者: JohnBull    时间: 2008-01-22 21:00
原帖由 flw 于 2008-1-22 20:53 发表

理论上来讲,只让对方回答“是”还是“不是”可以得到任何自己想要的结果。


OK,不兜圈子了。

那你就直接谈谈使用UDP实现变长分组通信的方法吧。
作者: flw    时间: 2008-01-22 21:00
原帖由 JohnBull 于 2008-1-22 20:55 发表


我们的实现方案应该是简化编程,而不是繁化。

如果对于某种复杂协议,使用les/yacc能够简化设计,为什么不用呢?
而对于多数简单协议,使用fgets/strsep就能解决,为什么要动用lex/yacc呢?

我的两条 man 命令是对你的两条 man 命令的有力补充,而不是最佳替代,
你又放空枪了~

作者: flw    时间: 2008-01-22 21:01
原帖由 JohnBull 于 2008-1-22 21:00 发表


OK,不兜圈子了。

那你就直接谈谈使用UDP实现变长分组通信的方法吧。

老师,我不会。可以去你的班里旁听吗?
作者: JohnBull    时间: 2008-01-22 21:05
原帖由 cugb_cat 于 2008-1-22 20:57 发表
不过诸如传文件之类的,不要长度就不好说了吧。


对啊,你可以挑起论战啊!
然后我可以嘴硬说文件也可以通过经过URL安全的base64编码的方法进行文本方式传输啊!
或者反驳你:如果恶意的客户机给出一个比实际长度更长的长度信息,我这边岂不是要傻等到超时?对方要是持续发起此类连接岂不成了DoS?
作者: JohnBull    时间: 2008-01-22 21:09
原帖由 flw 于 2008-1-22 21:01 发表

老师,我不会。可以去你的班里旁听吗?


可以呀,我一般教学生2种方法,一种可用于任意类型的socket,缺点是需要一个丑陋的长度字段;另一种一般用于UDP,不需要丑陋的长度字段。

看在你是版主的交情上,我给你打97折吧
作者: JohnBull    时间: 2008-01-22 21:10
原帖由 flw 于 2008-1-22 21:00 发表

我的两条 man 命令是对你的两条 man 命令的有力补充,而不是最佳替代,
你又放空枪了~


我也没说你说错了啊!我是对诸位看官解释一下何时使用何物的原则。也是对我们俩帖子的进一步补充啊
作者: cugb_cat    时间: 2008-01-22 21:10
原帖由 JohnBull 于 2008-1-22 21:05 发表


对啊,你可以挑起论战啊!
然后我可以嘴硬说文件也可以通过经过URL安全的base64编码的方法进行文本方式传输啊!
或者反驳你:如果恶意的客户机给出一个比实际长度更长的长度信息,我这边岂不是要 ...


偶向来嘴拙,起了论战也论不过,所以见了论战基本都躲开。
作者: JohnBull    时间: 2008-01-22 21:22
原帖由 cugb_cat 于 2008-1-22 21:10 发表


偶向来嘴拙,起了论战也论不过,所以见了论战基本都躲开。


论战不等于吵架,有观点尽管说出来无妨,闹着玩呗。


我说的也不一定对,觉得有问题尽管讲
作者: cugb_cat    时间: 2008-01-22 21:32
原帖由 JohnBull 于 2008-1-22 21:22 发表


论战不等于吵架,有观点尽管说出来无妨,闹着玩呗。


我说的也不一定对,觉得有问题尽管讲


作者: davycu    时间: 2008-01-23 19:37
捧腹




欢迎光临 Chinaunix (http://bbs.chinaunix.net/) Powered by Discuz! X3.2