winsock中的send()recv()函数使用的一些问题

dos5gw 2010-06-22 01:44:45

int send( SOCKET s, const char FAR *buf, int len, int flags );


(1)参数buf是否一定是以'\0'结尾的? 如果不是的话,函数如何判断buf是否全部拷贝进s的缓冲区?

(2)如果buf是以'\0'结尾的字符串,最后的'\0'是不是也进入了socket的"消息体"呢? 可能这个消息体用的不是很恰当;

(3)关于参数len, 我看孙鑫的那本<VC++深入详解>里的例子:
send(sockClient, "this is lizi" ,strlen("this is lizi")+1 ,0);
这里的len=strlen()+1, 是不是也吧\0这个结束符放进了消息体?


int recv( SOCKET s, char FAR *buf, int len, int flags );

(1)recv的使用前先为buf申请足够的空间,比如这里char buffer[100],但是这样调用recv(sock,buffer,200,0)或者len是小于100的数,这样会出现什么情况?
(2)如果如下的代码:
char buffer[100];
recv(sock,buffer,100,0);
如何才能用buffer[]数组的下标操作receive的字节,(可能这里没描述清楚,比如实际收到了abcdef六个字节,那么buffer[6]~buffer[99]中不是有效数据,如何才能避免访问到buffer[6]之后的元素呢?)
...全文
370 9 打赏 收藏 转发到动态 举报
写回复
用AI写文章
9 条回复
切换为时间正序
请发表友善的回复…
发表回复
Shrek_MyCpp 2010-06-22
  • 打赏
  • 举报
回复
二、关于recv():
1. 造成的后果就是程序崩溃。recv是从socket缓冲区拷贝到程序缓冲区,len决定了将拷贝多少个字节到程序缓冲区buf中。试想,当len大于buf的长度,多余的字节肯定会覆盖程序的栈空间。
2. 调用完recv后,是根据len来确定buf的实际内容,而不是根据buf的定义长度。要预先约定好或者动态约定好,recv的len长度。而且,此时的len=100没有任何意义,因为6-99的数值,可能并不是你想从socket缓存中拷贝出来的,但是事实上,你确实从socket缓存中,拷贝了100个字符,而不仅仅是"abcdef"。另外,你每次调用recv之前,最好把buf先清空一下。
Shrek_MyCpp 2010-06-22
  • 打赏
  • 举报
回复
首先,感谢CSDN,给大家提供一个交流和共同进步的平台!
最近一个月,开发了C/S模式的某工具,积累了一些经验,特来分享。
一、关于send():
1. len和结束符0没有任何关系。send将程序缓冲区拷贝到socket缓冲区,是调用了类似memcpy的函数,而不是strcpy,这将无视0的存在,只和len有关。
2. 这个问题和1是同一个问题。结束符是否被写入消息体内,取决于len。buf是次要的,len才是关键。
3. 是的。参数"abc"本身就是abc0,strlen是abc的长度,+1就包含了0。
wolffan3150 2010-06-22
  • 打赏
  • 举报
回复
(1)recv的使用前先为buf申请足够的空间,比如这里char buffer[100],但是这样调用recv(sock,buffer,200,0)或者len是小于100的数,这样会出现什么情况?
如果实际数据少于100,那么没问题,
如果超过就会数组越界


(2)如果如下的代码:
char buffer[100];
recv(sock,buffer,100,0);
如何才能用buffer[]数组的下标操作receive的字节,(可能这里没描述清楚,比如实际收到了abcdef六个字节,那么buffer[6]~buffer[99]中不是有效数据,如何才能避免访问到buffer[6]之后的元素呢?)

如果收到6个字符,其后都是无效的,
LZ应该
这样
int iRet = recv(sock,buffer,100,0);
iRet 会返回真实收到的数据数,
存在以buffer为首的地址里直接访问就可以了

建议LZ看书

================

(1)参数buf是否一定是以'\0'结尾的? 如果不是的话,函数如何判断buf是否全部拷贝进s的缓冲区?

char* 可以是字符串,也可完全不是字符只不过用char表示,如果len长度末尾包含'\0'
那就是,否则不是 \0 结尾,因为 buff 可能是二进制数据,不一定就是字符串,第三个参数len就是表示 buff 的长度的

(2)如果buf是以'\0'结尾的字符串,最后的'\0'是不是也进入了socket的"消息体"呢? 可能这个消息体用的不是很恰当;
char FAR *buf 不一定是字符串

(3)关于参数len, 我看孙鑫的那本<VC++深入详解>里的例子:
send(sockClient, "this is lizi" ,strlen("this is lizi")+1 ,0);
这里的len=strlen()+1, 是不是也吧\0这个结束符放进了消息体?

是的
stonewater 2010-06-22
  • 打赏
  • 举报
回复
buf只不过是你要发送数据的起始地址,要发送的长度由len决定,不一定发送的是字符串
Eleven 2010-06-22
  • 打赏
  • 举报
回复
send发送的东西也不一定是字符串啊,字节数组,结构体什么都可以。。。
tufaqing 2010-06-22
  • 打赏
  • 举报
回复
这个全部都是由自己决定的,而和字符串无关,len决定buf中发送的长度。
xfill 2010-06-22
  • 打赏
  • 举报
回复
[Quote=引用楼主 dos5gw 的回复:]
如何才能避免访问到buffer[6]之后的元素呢?)
[/Quote]

这个显然是你没自己实际输过这个代码,这个情况根本不存在,你完全可以控制住你需要使用多少长度的缓冲区。

建议你看书,配合着再把代码自己输入一遍,这样才能真正掌握。
xfill 2010-06-22
  • 打赏
  • 举报
回复
1. 不是 \0 结尾,因为 buff 可能是二进制数据,不一定就是字符串,第三个参数len就是表示 buff 的长度的

2. 这个假设就不成立了,略过

3. +1是为了发送 '\0’字符,比如 char buf = "hello" 你发送 strlen(buf) 的话是 5 接收到的就是 hello 这5个字符,那么 printf 的话就会吧后面的内存也打印出来,因为字符串是 \0 结束,所以他多发一个字节,就是把 \0 发送过去。

4. char buf[100]; recv(s, buf, 200, ...); 这样的话会造成缓冲区溢出,缓冲区溢出如果被利用的话,你的程序就存在漏洞了。当然,不是所有的缓冲区溢出情况都可以利用。

5. recv 返回值是一个 int 类型,返回的就是接收到的数据的长度,比如

int ret = recv(s, buf, 100, 0); 接收到 hello 5个字节的话

ret = 5;
yanran_hill 2010-06-22
  • 打赏
  • 举报
回复
1.send是不是把内存首地址buf,长度为len的数据,发送到socket,是否阻塞发送,根据情况而定
也就是说send的返回值,有可能小于len.
如果把buf内容看作是一个字符串的话,那么是否有'\0'与send没有任何关系,如果有的话,这也是调用者(开发者)自己做的约定,与send本身无关。
2.recv的返回值,表示接收到的实际字节数。因此如果能够明确收到多少字节的数据,可以使用ReadN方式循环recv

18,356

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC 网络编程
c++c语言开发语言 技术论坛(原bbs)
社区管理员
  • 网络编程
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

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