【原文链接】http://www.newsmth.net/nForum/#!article/Programming/79070
发信站: 水木社区 (Thu Jan 23 16:51:12 2014)
来 源: 114.249.217.103
【以下内容由 daoyu 转寄于 Programming 版】
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Sun Jan 19 19:21:40 2014) 在
【 [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
1 TCP协议编程中,client端调用send()发送长度为5000的字符串,server端设定接收的BUF_SIZE=1023,总共接受了5次,共(5*1023=5115),超过了发送端发送的数量,这样合理吗?
2 利用setsockopt()设定TCP发送缓冲区大小/TCP接收缓冲区大小,貌似都没有起作用,不知道为什么?
code如下
server端
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define BUF_SIZE 1024
int main(int argc, char* argv[])
{
if(argc <= 2)
{
printf("usage: %s ip_address port_number\n", (argv[0]));
return 1;
}
const char* ip = argv[1];
int port = atoi(argv[2]);
int sock = socket(PF_INET, SOCK_STREAM, 0);
printf("sock = %d\n", sock);
assert(sock >= 0);
struct sockaddr_in address;
bzero(&address, sizeof(address));
address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &address.sin_addr);
address.sin_port = htons(port);
int recbuf = atoi(argv[3]);
int len = sizeof(recbuf);
//下面两行设与不设,结果是相同的
//setsockopt(sock, SOL_SOCKET, SO_RCVBUF, &recbuf, sizeof(recbuf));
//getsockopt(sock, SOL_SOCKET, SO_RCVBUF, &recbuf, (socklen_t*)&len);
printf("the tcp receive buffer size after setting is %d\n", recbuf);
int ret = bind(sock, (struct sockaddr*)&address, sizeof(address));
assert(ret != -1);
ret = listen(sock, 5);
assert(ret != -1);
struct sockaddr_in server;
socklen_t server_addrlength = sizeof(server);
int connfd = accept(sock, (struct sockaddr*)&server, &server_addrlength);
if(connfd <0)
{
printf("errno is: %d\n", errno);
}
else
{
char buffer[BUF_SIZE];
memset(buffer, '\0', BUF_SIZE);
while(recv(connfd, buffer, BUF_SIZE-1, 0) > 0){printf("buffer=%s\n", buffer);}
close(connfd);
}
close(sock);
return 0;
}
client端
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <signal.h>
#include <unistd.h>
#include <stdlib.h>
#include <assert.h>
#include <stdio.h>
#include <string.h>
#include <errno.h>
#define BUFFER_SIZE 5000
int main(int argc, char* argv[])
{
if(argc <= 2)
{
printf("usage: %s ip_address port_number\n", argv[0]);
return 1;
}
const char* ip = argv[1];
int port = atoi(argv[2]);
int sock = socket(PF_INET, SOCK_STREAM, 0);
printf("sock = %d\n", sock);
assert(sock >= 0);
struct sockaddr_in client_address;
bzero(&client_address, sizeof(client_address));
client_address.sin_family = AF_INET;
inet_pton(AF_INET, ip, &client_address.sin_addr);
client_address.sin_port = htons(port);
int sendbuf = atoi(argv[3]);
int len = sizeof(sendbuf);
//下面两行设与不设,结果是相同的
//setsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, sizeof(sendbuf));
//getsockopt(sock, SOL_SOCKET, SO_SNDBUF, &sendbuf, (socklen_t *)&len);
printf("the top send buffer size after setting is %d\n", sendbuf);
if(connect(sock, (struct sockaddr*)&client_address, sizeof(client_address))!=-1)
{
char buffer[BUFFER_SIZE];
memset(buffer,'a',BUFFER_SIZE);
send(sock, buffer, BUFFER_SIZE, 0);
}
close(sock);
return 0;
}
☆─────────────────────────────────────☆
vonNeumann (劣币驱逐良币) 于 (Sun Jan 19 19:36:44 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
recv 的返回值不只是告诉你成功失败,它还告诉你实际收了多少字节,读操作不一定能填满缓冲区
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 1 TCP协议编程中,client端调用send()发送长度为5000的字符串,server端设定接收的BUF_SIZE=1023,总共接受了5次,共(5*1023=5115),超过了发送端发送的数量,这样合理吗?
: 2 利用setsockopt()设定TCP发送缓冲区大小/TCP接收缓冲区大小,貌似都没有起作用,不知道为什么?
: code如下
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Sun Jan 19 19:51:28 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
哦,刚才打印了一下recv()的返回值,共执行了五次,分别是:1023,1023,1023,1023,908。
返回值的结果是对的,总共是5000.
但是打印输出接收到的字符串不对,每次都是1023个字符,共1023*5=1115,这是什么原因呢?
"读操作不一定能填满缓冲区",请问这句话是什么意思啊?从结果来看,server端接受到的值确实已经超了实际发送的值。
【 在 vonNeumann 的大作中提到: 】
: recv 的返回值不只是告诉你成功失败,它还告诉你实际收了多少字节,读操作不一定能填满缓冲区
:
☆─────────────────────────────────────☆
Orpherus (奥路菲) 于 (Sun Jan 19 19:59:09 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
兄台还是没有理解C的字符串
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 哦,刚才打印了一下recv()的返回值,共执行了五次,分别是:1023,1023,1023,1023,908。
: 返回值的结果是对的,总共是5000.
: 但是打印输出接收到的字符串不对,每次都是1023个字符,共1023*5=1115,这是什么原因呢?
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Sun Jan 19 20:05:14 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
说说看。。。
【 在 Orpherus 的大作中提到: 】
: 兄台还是没有理解C的字符串
:
☆─────────────────────────────────────☆
Orpherus (奥路菲) 于 (Sun Jan 19 20:15:39 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
字符串函数都依赖\0字符做结尾,你的\0在哪里?
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 说说看。。。
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Sun Jan 19 20:29:21 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
这是字符数组哦,不是字符串
看这个例子:
#define BUF_SIZE 10
#define BUF_SIZE1 20
char buffer[BUF_SIZE];
memset(buffer,'a',BUF_SIZE);
char buffer1[BUF_SIZE1];
memset(buffer1, '\0', BUF_SIZE1);
strcpy(buffer1, buffer);
printf("%s\n", buffer1);
显示结果正确,输出10个a:
buffer1里输出aaaaaaaaaa
我的理解有问题吗?
【 在 Orpherus 的大作中提到: 】
: 字符串函数都依赖\0字符做结尾,你的\0在哪里?
:
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Sun Jan 19 20:33:16 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
啊,对了,字符数组不能用strcpy。。。
【 在 AnneSun 的大作中提到: 】
: 这是字符数组哦,不是字符串
: 看这个例子:
: #define BUF_SIZE 10
: ...................
☆─────────────────────────────────────☆
treesnaiL (彪叔) 于 (Sun Jan 19 20:40:01 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
打印输出的%s是打印的字符串,也就是说以0结尾的。
明显你打印输出的时候越界了
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 哦,刚才打印了一下recv()的返回值,共执行了五次,分别是:1023,1023,1023,1023,908。
: 返回值的结果是对的,总共是5000.
: 但是打印输出接收到的字符串不对,每次都是1023个字符,共1023*5=1115,这是什么原因呢?
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Sun Jan 19 20:46:10 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
对!
刚才在client端把'\0’加上,输出就正确了
还有一个问题:
setsockopt设置了tcp发送缓冲区/接受缓存区,为何不起作用呢?
【 在 treesnaiL 的大作中提到: 】
: 打印输出的%s是打印的字符串,也就是说以0结尾的。
: 明显你打印输出的时候越界了
:
☆─────────────────────────────────────☆
Orpherus (奥路菲) 于 (Sun Jan 19 20:56:25 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
不仅是strcpy,所有字符串函数都不能用
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 啊,对了,字符数组不能用strcpy。。。
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Sun Jan 19 20:58:06 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
恩,这次一定牢牢记住!
【 在 Orpherus 的大作中提到: 】
: 不仅是strcpy,所有字符串函数都不能用
:
☆─────────────────────────────────────☆
poggy (P股决定NoZ) 于 (Mon Jan 20 01:35:43 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 对!
: 刚才在client端把'\0’加上,输出就正确了
: 还有一个问题:
: ...................
你接收有问题
接收的while循环里面, 不是每次都清0, 而只是while前面清了一次是不行的
第四次接收后的数组内容是 1024个'a'
而最后一次908个, 但是后面的 '\0' 没有了
改正:
要么 用接收长度作下标, 置一个 '\0', 要么, 整个接收buffer,
每次接收前都清零
☆─────────────────────────────────────☆
zbz4 (wind) 于 (Mon Jan 20 09:59:37 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
看来菜鸟基础还是不稳固阿,还是要勤加练习阿
【 在 AnneSun 的大作中提到: 】
: 恩,这次一定牢牢记住!
:
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 15:33:33 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
是的,问题原因是字符数组和字符串没分清楚,谢谢哈!
【 在 poggy 的大作中提到: 】
:
: 你接收有问题
: 接收的while循环里面, 不是每次都清0, 而只是while前面清了一次是不行的
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 15:34:31 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
恩,还请大牛多加指导。。。
【 在 zbz4 的大作中提到: 】
: 看来菜鸟基础还是不稳固阿,还是要勤加练习阿
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 19:16:57 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
您好,请教一个问题,关于setsockopt()/getsockopt()里第三个参数设置成SO_RCVBUF/SO_SNDBUF.
SO_RCVBUF是设置TCP接收缓冲区大小
SO_SNDBUF是设置TCP发送缓冲区大小
目前client和server端分别设置为SO_SNDBUF/SO_RCVBUF:1000
但是貌似没起作用啊
程序结果还是用的send()/recv()中的缓存区大小。
想问一下:
这两个缓冲区设置有何区别?
SO_RCVBUF/SO_SNDBUF什么时候能起作用啊?
【 在 vonNeumann 的大作中提到: 】
: recv 的返回值不只是告诉你成功失败,它还告诉你实际收了多少字节,读操作不一定能填满缓冲区
:
☆─────────────────────────────────────☆
vonNeumann (劣币驱逐良币) 于 (Mon Jan 20 19:26:09 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
这两个参数不是你想的那个意思,SO_RCVBUF 是控制内核内为一个连接准备多大接受缓冲区(这个缓冲区满了内核就要开始丢包),SO_SNDBUF 变大能让内核多暂存点待发数据(send 调用被阻塞的可能性小一点),并不能控制内核何时开始实际发送数据。
如果你只是想偷懒不想循环 recv,加 MSG_WAITALL
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 您好,请教一个问题,关于setsockopt()/getsockopt()里第三个参数设置成SO_RCVBUF/SO_SNDBUF.
: SO_RCVBUF是设置TCP接收缓冲区大小
: SO_SNDBUF是设置TCP发送缓冲区大小
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 19:43:23 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
【 在 vonNeumann 的大作中提到: 】
: 这两个参数不是你想的那个意思,SO_RCVBUF 是控制内核内为一个连接准备多大接受缓冲区(这个缓冲区满了内核就要开始丢包),SO_SNDBUF 变大能让内核多暂存点待发数据(send 调用被阻塞的可能性小一点),并不能控制内核何时开始实际发送数据。
:
: 如果你只是想偷懒不想循环 recv,加 MSG_WAITALL
: ...................
看这个例子:
现在server端设置的recv()中缓冲区长度为5000;setsockopt()中SO_RCVBUF=1000;
client端设置send()的缓冲区长度也是5000,setsockopt()中SO_RCVBUF=1000;
结果:
server端:getsockopt()返回2144(按书上说是系统SO_RCVBUF加倍,或根据系统的默认最小值,暂且这么理解)
程序打印输出了5000个字符。
client端:getsockopt()返回1000
貌似SO_RCVBUF(2144)小于recv()中缓冲区长度(5000),但是它也没有丢包啊,什么原因?
☆─────────────────────────────────────☆
Orpherus (奥路菲) 于 (Mon Jan 20 19:55:05 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
这几个参数跟丢不丢包没有什么关系,为什么你会觉得会造成丢包呢?
把池子里的水舀干,瓶子大就少几次,瓶子小就多弄几次,最终都会完成
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 看这个例子:
: 现在server端设置的recv()中缓冲区长度为5000;setsockopt()中SO_RCVBUF=1000;
: client端设置send()的缓冲区长度也是5000,setsockopt()中SO_RCVBUF=1000;
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 20:07:07 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
不是缓冲区满了,内核开始丢包吗。。。
那这两个参数SO_SNDBUF/SO_RCVBUF到底什么意思呢?
【 在 Orpherus 的大作中提到: 】
: 这几个参数跟丢不丢包没有什么关系,为什么你会觉得会造成丢包呢?
: 把池子里的水舀干,瓶子大就少几次,瓶子小就多弄几次,最终都会完成
:
☆─────────────────────────────────────☆
Orpherus (奥路菲) 于 (Mon Jan 20 20:10:26 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
满了可以丢掉,也可以拒绝新的进来,第二种就不会有丢失
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 不是缓冲区满了,内核开始丢包吗。。。
: 那这两个参数SO_SNDBUF/SO_RCVBUF到底什么意思呢?
☆─────────────────────────────────────☆
Orpherus (奥路菲) 于 (Mon Jan 20 20:13:13 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
食堂3个窗口卖饭菜,有100个人要买饭,3个窗口满了后面的人就吃不上饭了?
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 不是缓冲区满了,内核开始丢包吗。。。
: 那这两个参数SO_SNDBUF/SO_RCVBUF到底什么意思呢?
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 20:18:18 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
现在SO_RCVBUF(2144)< recv的缓冲区(5000),server端只进行了一次recv()就将所有数据接收到。
那server端是先接收了2144,然后又接收2144,最后接收712,这样完成的接收吗?
【 在 Orpherus 的大作中提到: 】
: 满了可以丢掉,也可以拒绝新的进来,第二种就不会有丢失
:
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 20:20:09 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
额,能吃上饭。。。但是要多次卖饭。
server端也应该多次recv,难道不是吗?
【 在 Orpherus 的大作中提到: 】
: 食堂3个窗口卖饭菜,有100个人要买饭,3个窗口满了后面的人就吃不上饭了?
:
☆─────────────────────────────────────☆
Orpherus (奥路菲) 于 (Mon Jan 20 20:54:26 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
你还是找本书看看吧,速成的也行
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 现在SO_RCVBUF(2144)< recv的缓冲区(5000),server端只进行了一次recv()就将所有数据接收到。
: 那server端是先接收了2144,然后又接收2144,最后接收712,这样完成的接收吗?
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 21:00:21 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
现在就是在看书。。。
【 在 Orpherus 的大作中提到: 】
: 你还是找本书看看吧,速成的也行
:
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 21:40:03 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
在网上查了一下,之前不起作用,是不是这两个配置造成的呀?
net.core.rmem_max
net.core.wmem_max
(因为设置的太小SO_SNDBUF/SO_RCVBUF=1000,它按照系统的默认值来设置)
刚才试了一下send()/recv()的buffer设成500000;SO_SNDBUF/SO_RCVBUF设成40000
结果server端多次接收了,每次接收的大小为:40960。
谢谢你的帮助~~
【 在 Orpherus 的大作中提到: 】
: 你还是找本书看看吧,速成的也行
:
☆─────────────────────────────────────☆
vonNeumann (劣币驱逐良币) 于 (Mon Jan 20 21:56:50 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
那个缓冲区的意思,不是说要满了才让你读。。只要有数据来了,就要马上允许应用程序读到,这符合绝大多数程序的期望。这个缓冲区大小只控制内核最多能帮你暂存多数数据。
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 看这个例子:
: 现在server端设置的recv()中缓冲区长度为5000;setsockopt()中SO_RCVBUF=1000;
: client端设置send()的缓冲区长度也是5000,setsockopt()中SO_RCVBUF=1000;
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 23:11:21 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
恩,谢谢哈!
之前设置的值不起作用,是不是因为太小了(SO_SNDBUF/SO_RCVBUF=1000)?
所以系统用默认值net.core.rmem_max/net.core.wmem_max
试了一下send()/recv()的buffer设成500000;SO_SNDBUF/SO_RCVBUF设成40000
结果server端多次接收了,每次接收的大小为:40960。
【 在 vonNeumann 的大作中提到: 】
: 那个缓冲区的意思,不是说要满了才让你读。。只要有数据来了,就要马上允许应用程序读到,这符合绝大多数程序的期望。这个缓冲区大小只控制内核最多能帮你暂存多数数据。
:
☆─────────────────────────────────────☆
hgoldfish (老鱼) 于 (Mon Jan 20 23:35:27 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
借人气做个广告。netprg版快关版了。
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 恩,谢谢哈!
: 之前设置的值不起作用,是不是因为太小了(SO_SNDBUF/SO_RCVBUF=1000)?
: 所以系统用默认值net.core.rmem_max/net.core.wmem_max
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Mon Jan 20 23:41:05 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
netprg是网络编程吗?
【 在 hgoldfish 的大作中提到: 】
: 借人气做个广告。netprg版快关版了。
:
☆─────────────────────────────────────☆
vonNeumann (劣币驱逐良币) 于 (Tue Jan 21 00:22:48 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
。。。
即使你这样设置了,仍然不能对 recv 一次会返回多数据作任何假设的。。你换个网络差点的环境试试。。
说过了,如果想要 recv 每次都把缓冲区(这里指的你传给 recv 的 buffer,不是 SO_SNDBUF/SO_RCVBUF 指的那个!)填满,应该用 MSG_WAITALL,而不是试图去调内核的网络缓冲区大小。
还是去找本教程认真从头读下吧。。
另外,涉及 IO 的操作,尤其涉及网络的,真的不要偷懒,返回值必须认真检查,真实网络环境下什么事都会发生
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 恩,谢谢哈!
: 之前设置的值不起作用,是不是因为太小了(SO_SNDBUF/SO_RCVBUF=1000)?
: 所以系统用默认值net.core.rmem_max/net.core.wmem_max
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 10:17:58 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
好的,谢谢哈!
有没有好的教程推荐一下,目前看的是<Linux高性能服务器编程>,讲的不是很细。。。
【 在 vonNeumann 的大作中提到: 】
: 。。。
: 即使你这样设置了,仍然不能对 recv 一次会返回多数据作任何假设的。。你换个网络差点的环境试试。。
: 说过了,如果想要 recv 每次都把缓冲区(这里指的你传给 recv 的 buffer,不是 SO_SNDBUF/SO_RCVBUF 指的那个!)填满,应该用 MSG_WAITALL,而不是试图去调内核的网络缓冲区大小。
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 10:21:11 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
请问有没有入门的教程推荐一下啊,目前看的教程讲的不细。。。
【 在 Orpherus 的大作中提到: 】
: 你还是找本书看看吧,速成的也行
:
☆─────────────────────────────────────☆
Orpherus (奥路菲) 于 (Tue Jan 21 10:29:14 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
速成看apue第三版第16章,详细的看网络编程第三版,进阶看tcpip详解
我觉得一般写写带网络的应用看完速成就差不多了,没必要看详解
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 请问有没有入门的教程推荐一下啊,目前看的教程讲的不细。。。
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 10:42:11 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
好的,网上居然可以下载到,先看着,谢啦!
【 在 Orpherus 的大作中提到: 】
: 速成看apue第三版第16章,详细的看网络编程第三版,进阶看tcpip详解
: 我觉得一般写写带网络的应用看完速成就差不多了,没必要看详解
:
☆─────────────────────────────────────☆
zbz4 (wind) 于 (Tue Jan 21 13:35:10 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
我看了这个邮件的系列,没闹明白到底是什么问题,特意去搜了一下
没发现多少问题啊?
首先,write成功返回,只是buf中的数据被复制到了kernel中的TCP发送缓冲区。至于数据什么时候被发往网络,什么时候被对方主机接收,什么时候被对方进程读取,系统调用层面不会给予任何保证和通知。
write在什么情况下会阻塞?当kernel的该socket的发送缓冲区已满时。对于每个socket,拥有自己的send buffer和receive buffer。从Linux 2.6开始,两个缓冲区大小都由系统来自动调节(autotuning),但一般在default和max之间浮动。
# 获取socket的发送/接受缓冲区的大小:(后面的值是在我在Linux 2.6.38 x86_64上测试的结果)
sysctl net.core.wmem_default #126976
sysctl net.core.wmem_max #131071
sysctl net.core.wmem_default #126976
sysctl net.core.wmem_max #131071
已经发送到网络的数据依然需要暂存在send buffer中,只有收到对方的ack后,kernel才从buffer中清除这一部分数据,为后续发送数据腾出空间。接收端将收到的数据暂存在receive buffer中,自动进行确认。但如果socket所在的进程不及时将数据从receive buffer中取出,最终导致receive buffer填满,由于TCP的滑动窗口和拥塞控制,接收端会阻止发送端向其发送数据。这些控制皆发生在TCP/IP栈中,对应用程序是透明的,应用程序继续发送数据,最终导致send buffer填满,write调用阻塞。
一般来说,由于接收端进程从socket读数据的速度跟不上发送端进程向socket写数据的速度,最终导致发送端write调用阻塞。
而read调用的行为相对容易理解,从socket的receive buffer中拷贝数据到应用程序的buffer中。read调用阻塞,通常是发送端的数据没有到达。
几个重要的结论:
1. read总是在接收缓冲区有数据时立即返回,而不是等到给定的read buffer填满时返回。
只有当receive buffer为空时,blocking模式才会等待,而nonblock模式下会立即返回-1(errno = EAGAIN或EWOULDBLOCK)
2. blocking的write只有在缓冲区足以放下整个buffer时才返回(与blocking read并不相同)
nonblock write则是返回能够放下的字节数,之后调用则返回-1(errno = EAGAIN或EWOULDBLOCK)
对于blocking的write有个特例:当write正阻塞等待时对面关闭了socket,则write则会立即将剩余缓冲区填满并返回所写的字节数,再次调用则write失败(connection reset by peer),这正是下个小节要提到的:
【 在 AnneSun 的大作中提到: 】
: 好的,网上居然可以下载到,先看着,谢啦!
:
☆─────────────────────────────────────☆
muser (负尽千重罪,练就不死心) 于 (Tue Jan 21 14:52:41 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
本来想:啊,你敲了这么多这么清楚的.........然后看最后一句:这正是下个小节要提到的:
hehe....
【 在 zbz4 的大作中提到: 】
: 我看了这个邮件的系列,没闹明白到底是什么问题,特意去搜了一下
: 没发现多少问题啊?
: 首先,write成功返回,只是buf中的数据被复制到了kernel中的TCP发送缓冲区。至于数据什么时候被发往网络,什么时候被对方主机接收,什么时候被对方进程读取,系统调用层面不会给予任何保证和通知。
: ...................
☆─────────────────────────────────────☆
muser (负尽千重罪,练就不死心) 于 (Tue Jan 21 14:55:29 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
无比同意。
前一段为了两端同时出现TIME_WAIT,我翻了几天材料。
【 在 vonNeumann 的大作中提到: 】
: 另外,涉及 IO 的操作,尤其涉及网络的,真的不要偷懒,返回值必须认真检查,真实网络环境下什么事都会发生
: ...................
☆─────────────────────────────────────☆
zbz4 (wind) 于 (Tue Jan 21 15:08:07 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
我也是从网上搜索的,感觉lz的疑问完全就在这一片小文章里,我只是节选一段
lz的疑问主要是没明白用户空间的buffer和内核空间的buffer的联系,
以及read/write的block/nonblock属性对buffer的操作,
按照这个文章的讲解的话,接受path中,只要有数据的话,用户空间的buffer就被填充,read就返回,这个数据的多少,是不是buffer满了,根本就是内核收到的数据的多少决定,一次来了很多数据,把buffer填充满了,也有可能阿,假如一次来了几个字节,也有可能,取决于网络如何接受到数据的多少,跟buffer大小没有很大关系
【 在 muser 的大作中提到: 】
: 本来想:啊,你敲了这么多这么清楚的.........然后看最后一句:这正是下个小节要提到的:
: hehe....
:
☆─────────────────────────────────────☆
muser (负尽千重罪,练就不死心) 于 (Tue Jan 21 15:21:26 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
你这引的是对的。
反正就是来了就掏一把,不管掏着多少,都走了。如果没有掏着,就看是等会儿、还是拎着空篮子走人了。
【 在 zbz4 的大作中提到: 】
: 我也是从网上搜索的,感觉lz的疑问完全就在这一片小文章里,我只是节选一段
: lz的疑问主要是没明白用户空间的buffer和内核空间的buffer的联系,
: 以及read/write的block/nonblock属性对buffer的操作,
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 16:15:15 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
非常感谢你的回复!
是不是这样的理解吗?
假定:内核缓冲区大小为5000字节
在block模式下:
目前内核缓冲区中有4000字节,
这时send()向内核要发送2000字节,则用户缓冲区先拷贝1000字节到内核到内核缓冲区(1000+4000=5000达到内核缓冲区大小),则内核缓冲区发送数据。当内核缓冲区发送完后,用户缓冲区向内核缓冲区拷贝剩余的1000字节的数据。
recv()接收到的数据大小也是内核缓冲区的大小为5000字节。
在unblock模式下:
无论内核缓冲区中有多少字节,都会立即发送,而不管其是否满。
recv()接收到的数据大小也一定是内核缓冲区大小。
【 在 zbz4 的大作中提到: 】
: 我看了这个邮件的系列,没闹明白到底是什么问题,特意去搜了一下
: 没发现多少问题啊?
: 首先,write成功返回,只是buf中的数据被复制到了kernel中的TCP发送缓冲区。至于数据什么时候被发往网络,什么时候被对方主机接收,什么时候被对方进程读取,系统调用层面不会给予任何保证和通知。
: ...................
☆─────────────────────────────────────☆
Orpherus (奥路菲) 于 (Tue Jan 21 16:18:31 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
不对
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 非常感谢你的回复!
: 是不是这样的理解吗?
: 假定:内核缓冲区大小为5000字节
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 16:21:56 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
我再看看。。。
【 在 Orpherus 的大作中提到: 】
: 不对
:
☆─────────────────────────────────────☆
Orpherus (奥路菲) 于 (Tue Jan 21 16:22:26 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
一次send/recv多少,跟缓冲区大小无关,跟网络环境和协议实现有关
recv(tcp)的那头,只保证字节流顺序和数量一致,每次收到多少则不保证
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 非常感谢你的回复!
: 是不是这样的理解吗?
: 假定:内核缓冲区大小为5000字节
: ...................
☆─────────────────────────────────────☆
zbz4 (wind) 于 (Tue Jan 21 17:17:58 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
block/noblock模式只会影响到怎么把 用户buffer copy到 内核buffer 或者内核buffer copy 到用户buffer吧,
内核发送内核buffer的数据,那是内核的事情,你可以研究一下
比如,你把包裹送给顺丰或者ems之后,顺丰或者ems怎么投递包裹那是人家的事情,跟你没多大关系,是否凑齐一卡车再送 还是 来一个送一个,就不知道了,应该取一个折中吧
估计你得研究内核如何发送利用tcp/ip报文
【 在 AnneSun 的大作中提到: 】
: 非常感谢你的回复!
: 是不是这样的理解吗?
: 假定:内核缓冲区大小为5000字节
: ...................
☆─────────────────────────────────────☆
giantchen (研究僧) 于 (Tue Jan 21 18:13:32 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
换本好点的书看吧,UNPv1什么的。
【 在 AnneSun 的大作中提到: 】
: 好的,谢谢哈!
: 有没有好的教程推荐一下,目前看的是<Linux高性能服务器编程>,讲的不是很细。。。
:
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 18:20:39 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
也就是说当send()多次执行,将数据由user buffer拷贝到kernel buffer中(kernel buffer的大小由tcp_wmem/SO_SNDBUF来确定),而内核缓冲区将这些数据封装成一个或多个TCP报文段,send()的次数和TCP发送的TCP报文段的个数没有关系。
接收端收到多个TCP报文,并将其按照报文段的序号放到TCP的kernel buffer中(kernel buffer的大小由tcp_rmem/SO_RCVBUF来确定)。而程序在调用recv()的时候,可以一次读取,也可以多次读取,取决于recv()函数中的buffer的大小。
【 在 Orpherus 的大作中提到: 】
: 一次send/recv多少,跟缓冲区大小无关,跟网络环境和协议实现有关
: recv(tcp)的那头,只保证字节流顺序和数量一致,每次收到多少则不保证
:
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 18:31:40 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
恩,我需要买书
【 在 giantchen 的大作中提到: 】
: 换本好点的书看吧,UNPv1什么的。
: :
☆─────────────────────────────────────☆
zbz4 (wind) 于 (Tue Jan 21 18:38:32 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
勇敢的小白,
其实好多书买了最后没看就当废纸卖了
【 在 AnneSun 的大作中提到: 】
: 恩,我需要买书
:
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 18:43:08 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
呵呵,我也是买的好多书都没看。。。
不过以目前情况来看,确实需要买书
【 在 zbz4 的大作中提到: 】
: 勇敢的小白,
: 其实好多书买了最后没看就当废纸卖了
☆─────────────────────────────────────☆
zbz4 (wind) 于 (Tue Jan 21 18:45:17 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
你能把一本网上下载的电子书看好就不错了,买书简直就是装点门面
【 在 AnneSun 的大作中提到: 】
: 呵呵,我也是买的好多书都没看。。。
: 不过以目前情况来看,确实需要买书
:
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 18:49:51 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
恩,不过实在是不愿意看电子的,还是纸质的看着舒服,嘿嘿
btw,谢谢你的帮助哦!
【 在 zbz4 的大作中提到: 】
: 你能把一本网上下载的电子书看好就不错了,买书简直就是装点门面
☆─────────────────────────────────────☆
vonNeumann (劣币驱逐良币) 于 (Tue Jan 21 19:09:00 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
recv 指定的 buffer 大小只是一个因素。如果只有第一个包到了后面的没到,你给的 buffer 再大,也会马上返回给你第一个包的内容
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 也就是说当send()多次执行,将数据由user buffer拷贝到kernel buffer中(kernel buffer的大小由tcp_wmem/SO_SNDBUF来确定),而内核缓冲区将这些数据封装成一个或多个TCP报文段,send()的次数和TCP发送的TCP报文段的个数没有关系。
: 接收端收到多个TCP报文,并将其按照报文段的序号放到TCP的kernel buffer中(kernel buffer的大小由tcp_rmem/SO_RCVBUF来确定)。而程序在调用recv()的时候,可以一次读取,也可以多次读取,取决于recv()函数中的buffer的大小。
☆─────────────────────────────────────☆
heracules (NULL) 于 (Tue Jan 21 20:33:15 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
你把UNP这本书上讲为什么要用readn和writen搞清楚你就不会再问这么基本的问题了
【 在 AnneSun (AnneSun) 的大作中提到: 】
: 非常感谢你的回复!
: 是不是这样的理解吗?
: 假定:内核缓冲区大小为5000字节
: ...................
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 23:19:35 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
恩,记下了,谢谢哈!
【 在 vonNeumann 的大作中提到: 】
: recv 指定的 buffer 大小只是一个因素。如果只有第一个包到了后面的没到,你给的 buffer 再大,也会马上返回给你第一个包的内容
:
☆─────────────────────────────────────☆
AnneSun (AnneSun) 于 (Tue Jan 21 23:38:11 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
好的,明天看看这方面的内容,谢谢!
【 在 heracules 的大作中提到: 】
: 你把UNP这本书上讲为什么要用readn和writen搞清楚你就不会再问这么基本的问题了
☆─────────────────────────────────────☆
minos001 (米诺牛) 于 (Wed Jan 22 13:08:07 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
这个问题用 zeroMQ 这种协议就能解决了吧,保证发出的message 能按质按量收到
【 在 AnneSun 的大作中提到: 】
: 1 TCP协议编程中,client端调用send()发送长度为5000的字符串,server端设定接收的BUF_SIZE=1023,总共接受了5次,共(5*1023=5115),超过了发送端发送的数量,这样合理吗?
: 2 利用setsockopt()设定TCP发送缓冲区大小/TCP接收缓冲区大小,貌似都没有起作用,不知道为什么?
: code如下
: ...................
☆─────────────────────────────────────☆
fuse (baoxian) 于 (Thu Jan 23 09:23:42 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
搭车问个问题,这个情形下,不少于 PIPE_BUF bytes 的write是原子操作,这个是哪个层面的事情?pipe buffer 在内核?和这个socket 的 buffer有没有关系?
【 在 vonNeumann (劣币驱逐良币) 的大作中提到: 】
: recv 指定的 buffer 大小只是一个因素。如果只有第一个包到了后面的没到,你给的 buffer 再大,也会马上返回给你第一个包的内容
☆─────────────────────────────────────☆
vonNeumann (劣币驱逐良币) 于 (Thu Jan 23 10:03:58 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
【 在 fuse (baoxian) 的大作中提到: 】
: 搭车问个问题,这个情形下,不少于 PIPE_BUF bytes 的write是原子操作,这个是哪
: 个层面的事情?
系统调用层面的事情
长度不超过 PIPE_BUF 的写操作,系统保证写入的数据在最后的数据中也连在一起,中间不会被其他进程/线程写的数据打断
: pipe buffer 在内核?
是
: 和这个socket 的 buffer有没有关系?
有点吧,但 pipe 和 socket 的实现不一样,有些行为不见得一致。socket 没有保证小于多少的写操作原子,至少文档上没有不敢放心依赖
☆─────────────────────────────────────☆
justicezyx (又跑路在即) 于 (Thu Jan 23 10:52:52 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
极品新手!
【 在 AnneSun 的大作中提到: 】
: 1 TCP协议编程中,client端调用send()发送长度为5000的字符串,server端设定接收的BUF_SIZE=1023,总共接受了5次,共(5*1023=5115),超过了发送端发送的数量,这样合理吗?
: 2 利用setsockopt()设定TCP发送缓冲区大小/TCP接收缓冲区大小,貌似都没有起作用,不知道为什么?
: code如下
: ...................
☆─────────────────────────────────────☆
fuse (baoxian) 于 (Thu Jan 23 14:49:20 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
那写pipe会不会在写入100bytes的时候被signal打断?如果能被打断,这个原子操作如何解释?这中情形下无效?
【 在 vonNeumann (劣币驱逐良币) 的大作中提到: 】
: 系统调用层面的事情
: 长度不超过 PIPE_BUF 的写操作,系统保证写入的数据在最后的数据中也连在一起,中间不会被其他进程/线程写的数据打断
: 是
: ...................
☆─────────────────────────────────────☆
vonNeumann (劣币驱逐良币) 于 (Thu Jan 23 14:53:19 2014) 在
【 Re: [问题]socket编程中,send的数据量和recv的数据量不相同 】 的大作中提到:
从文档中貌似看不出来
别的系统我不敢肯定,Linux 2.6 下不会被打断,看过它的管道实现
【 在 fuse (baoxian) 的大作中提到: 】
: 那写pipe会不会在写入100bytes的时候被signal打断?如果能被打断,这个原子操作如何解释?这中情形下无效?