【发布时间】:2015-05-01 09:05:00
【问题描述】:
根据我的理解,每个socket都关联了两个缓冲区,一个发送缓冲区和一个接收缓冲区,所以当我调用send()函数时,发生的情况是要发送的数据会被放入发送缓冲区,现在 Windows 的职责就是将这个发送缓冲区的内容发送到另一端。
在阻塞套接字中,send() 函数在提供给它的全部数据都放入发送缓冲区之前不会返回。
那么发送缓冲区的大小是多少?
我执行了以下测试(发送 1 GB 的数据):
#include <stdio.h>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib")
#include <Windows.h>
int main()
{
// Initialize Winsock
WSADATA wsa;
WSAStartup(MAKEWORD(2, 2), &wsa);
// Create socket
SOCKET s = socket(AF_INET, SOCK_STREAM, 0);
//----------------------
// Connect to 192.168.1.7:12345
sockaddr_in address;
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("192.168.1.7");
address.sin_port = htons(12345);
connect(s, (sockaddr*)&address, sizeof(address));
//----------------------
// Create 1 GB buffer ("AAAAAA...A")
char *buffer = new char[1073741824];
memset(buffer, 0x41, 1073741824);
// Send buffer
int i = send(s, buffer, 1073741824, 0);
printf("send() has returned\nReturn value: %d\nWSAGetLastError(): %d\n", i, WSAGetLastError());
//----------------------
getchar();
return 0;
}
输出:
send() has returned
Return value: 1073741824
WSAGetLastError(): 0
send() 立即返回,这是否意味着发送缓冲区的大小至少为 1 GB?
这是关于测试的一些信息:
- 我正在使用 TCP 阻塞套接字。
- 我已连接到 LAN 计算机。
- 客户端 Windows 版本:Windows 7 Ultimate 64 位。
- 服务器 Windows 版本:Windows XP SP2 32 位(安装在 Virtual Box 上)。
编辑:我也尝试连接到 Google (173.194.116.18:80),得到了相同的结果。
编辑 2:我发现了一些奇怪的东西,将发送缓冲区设置为 64 KB 到 130 KB 之间的值将使 send() 按预期工作!
int send_buffer = 64 * 1024; // 64 KB
int send_buffer_sizeof = sizeof(int);
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)send_buffer, send_buffer_sizeof);
编辑 3: 事实证明(感谢 Harry Johnston)我以不正确的方式使用了 setsockopt(),这就是它的使用方式:
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&send_buffer, send_buffer_sizeof);
将发送缓冲区设置为 64 KB 和 130 KB 之间的值不会使 send() 按预期工作,而是将发送缓冲区设置为 0使它阻塞(这就是我注意到的,我没有任何关于这种行为的文档)。
所以我现在的问题是:我在哪里可以找到关于send()(可能还有其他套接字操作)如何在 Windows 下工作的文档?
【问题讨论】:
-
如果没有错误,send返回发送的总字节数,可以小于len参数中请求发送的字节数。 msdn.microsoft.com/en-us/library/windows/desktop/…
-
您可以通过
getsockopt()发现自己的尺寸。你怎么知道它立即返回?那个代码不能告诉你。 -
你可以告诉它立即返回(错误或无错误),因为他发送了一个 1GB 的缓冲区。除非您拥有超快的互联网,否则这将花费他很长时间。很可能失败了。
-
@Brandon 您无法从此代码中知道发送何时开始和结束。那里还有一个
connect(),这可能需要相当长的时间。他没有使用互联网,他使用的是局域网。 -
@EJP 其实我连接了谷歌(173.194.116.18:80),
send()也立即返回,没有错误。
标签: c++ windows sockets winapi tcp