Основываясь на моем понимании, каждый сокет связан с двумя буферами, буфером отправки и буфером приема, поэтому, когда я вызываю функцию send()
, происходит то, что отправляемые данные будут помещены в буфер отправки, и теперь Windows обязан отправлять содержимое этого буфера отправки на другой конец.
В блокирующем сокете функция send()
не возвращается, пока все данные, переданные ей, не будут помещены в буфер отправки.
Итак, каков размер буфера отправки?
Я выполнил следующий тест (отправка данных объемом 1 ГБ):
#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 ГБ?
Это информация о тесте:
- Я использую блокировку TCP-блокировки.
- Я подключился к LAN-машине.
- Клиентская версия Windows: 64-разрядная версия Windows 7 Ultimate.
- Сервер Windows версия: Windows XP SP2 32-разрядная (установлена в Virtual Box).
Изменить: Я также попытался подключиться к Google (173.194.116.18:80), и я получил те же результаты.
Изменить 2: Я обнаружил что-то странное, установив буфер отправки на значение от 64 КБ до 130 КБ, сделает 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: Оказалось (спасибо Гарри Джонстону), что я неправильно использовал setsockopt()
, вот как он используется:
setsockopt(s, SOL_SOCKET, SO_SNDBUF, (char*)&send_buffer, send_buffer_sizeof);
Настройка буфера отправки на значение от 64 КБ до 130 КБ не делает send()
работать как ожидалось, , а скорее устанавливает буфер отправки в 0
блокирует (это то, что я заметил в любом случае, у меня нет документации для этого поведения).
Итак, теперь мой вопрос: где я могу найти документацию о том, как send()
(и, возможно, другие операции сокета) работают под Windows?