您的位置:首页 > 理论基础 > 计算机网络

有关socket通信包大小的问题总结(UDP传输模式)

2011-07-06 23:09 323 查看
最近刚接触linux的编程,在pc机上编了两个socket通信的程序做测试,一个采用TCP的方式,另一个采用UDP的方式。不断增大传输数据包的大小,到180k大小时,UDP通信收不到包,阻塞在recvfrom(),而TCP方式仍然能正常工作。对于用SOCK_DGRAM创建的socket来发送UDP包,假如发送的数据过大,linux kernel 下面的TCP/IP stack 会重新分成小包发送的,对于应用程序来说,不需要关心数据大小。问题在于发送的数据大小超过了内核缓冲区的最大限制,这个限制好象是65535(默认情况下是64K)
通过使用函数setsockopt(ip_socket->socket.fd, SOL_SOCKET, SO_RCVBUF, &size, &len) ,改变接收缓冲区大小的属性。同理,setsockopt(ip_socket->socket.fd, SOL_SOCKET, SO_SNDBUF, &size, &len) 也可以改变发送缓冲区的大小。#define RMEM_MAX (1024*200)
{
/* dma: 内核默认设置接收BUF为64K,工作在0!14MB/S的低速情况下,当速度大于19MB/S时LINUX就
就会丢包 可以更改 /proc/sys/net/core/rmem_max 这个文件.
可使用如下命令进行更改echo 200000 > /proc/sys/net/core/rmem_max.
*/
FILE *f;
char buf[80];
int rmax;
f = fopen("/proc/sys/net/core/rmem_max", "rw");
if (f) {
fread(buf, 1, sizeof(buf), f);
sscanf(buf, "%d", &rmax); //从rmax中读取一个int赋值给buf
fclose(f);
if (rmax == 65535) {
sprintf(buf, "%d", RMEM_MAX); //将NEW_RMEM_MAX以%d的方式输出到buf中
f = fopen("/proc/sys/net/core/rmem_max", "w");
fwrite(buf, 1, strlen(buf)+1, f);
fclose(f);
new_rmem_max = RMEM_MAX;
} else
new_rmem_max = rmax;
}
}
结合以上信息总结:1.UDP方式传输一段完整数据的大小时受内核缓冲区限制的,比如在默认情况下缓冲区大小是64K,所以对于该情况下的socket接收或者发送方,最大可以一次性发送一个64K的数据。而对于socket底层的具体实现是将64K的数据拆分成N个小数据包,内部提供机制保证数据的可靠性,例如每个包的大小为1K,则分成64个包,从服务器端发送到客户端,客户端在本地缓冲区重新组成完整的数据提交给用户。底层的实现方式应该各不相同,但是对于上层结果都是一样的。如果超过了缓冲区大小则无法完成组包出现丢包等等现象。同理,对于200K则可以发送接收200K大小的数据。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息