有关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大小的数据。
通过使用函数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大小的数据。
相关文章推荐
- 有关socket通信包大小的问题总结(UDP传输模式)
- SOCKET客户端与服务端长时间通信后,会连接不上服务端的问题,以及server端UDP丢包的问题
- VC++使用socket进行TCP、UDP通信实例总结
- [经验总结]--关于socket通信传输非char型数组的解决方法
- Android中Socket通信之TCP与UDP传输原理
- 网络间通信socket传输任意格式任意大小的文件
- c++ udp的socket通信使用jsoncpp传输
- 网络间通信socket传输任意格式任意大小的文件
- SOCKET通信中TCP、UDP数据包大小的确定
- socket通信——通过Udp传输方式,将一段文字数据发送出去
- SOCKET通信中TCP、UDP数据包大小的确定
- TCP与UDP在socket中传输通信的区别
- linux CGI与命名管道非堵塞模式通信问题总结
- SOCKET通信中TCP、UDP数据包大小的确定
- Socket 通信原理(Android客户端和服务器以TCP&&UDP方式互通)(解决不可连的问题,解决方案在最后面)
- socket通信——通过Udp传输方式,将一段文字数据发送出去
- UDP传输包大小问题
- Android中Socket通信之TCP与UDP传输原理
- SOCKET通信中TCP、UDP数据包大小的确定
- Android中Socket通信之TCP与UDP传输原理