WinSock 2.2 send()函数总是返回我想要发送的所有字节!我在端口80上连接到google.com并发送随机t
字母的数据。我甚至尝试发送多达1GB的t
。它仍然返回所有发送的字节。我希望它能和我一起返回它可以容纳在数据包中的字节数,其余部分将由实现中的while循环处理,但它永远不会进入while循环内部!
我正在使用TCP / IPv4套接字。我知道我的互联网没有快速点亮,比我闪烁的速度快1GB。
此代码显示最重要的块。例如,省略了C字符串发送调用的包装器,它调用了我显示的发送。
调用测试代码
//prepare the long data string
int buffSize = 1 * 1000 * 1000 * 1000;
char *buff = new char[buffSize];
memset(buff, 't', buffSize);
buff[buffSize - 3] = '\n';
buff[buffSize - 2] = '\n';
buff[buffSize - 1] = '\0';
//send thee data
int bytesSent = socket->send(buff);
//verify all thee data is sent
CHECK(bytesSent == strlen(buff));
发送实施
int mySocket::send(const void *data, int length)
{
int bytesSent = ::send(socketDescriptor, (char*)data, length, 0);
if (bytesSent == SOCKET_ERROR) return -1;
while(bytesSent < length)
{
int sent = ::send(socketDescriptor, (char*)data + bytesSent, length - bytesSent, 0);
if (sent == SOCKET_ERROR) return bytesSent;
bytesSent += sent;
}
return bytesSent;
}
编辑1
因为这里开始混淆人们是包装
发送包装
int mySocket::send(const char * data_string)
{
return send(dataString, strlen(data_string));
}
编辑2
这是一个可以调试的完整工作示例。它产生相同的结果,它只是立即报告发送的所有字节。
#include <WinSock2.h>
#include <WS2tcpip.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib")
class mySocket
{
public:
mySocket(SOCKET sockeDesc)
{
socketDescriptor = sockeDesc;
}
int mySocket::send(const void *data, int length)
{
int bytesSent = ::send(socketDescriptor, (char*)data, length, 0);
if (bytesSent == SOCKET_ERROR) return -1;
while (bytesSent < length)
{
int sent = ::send(socketDescriptor, (char*)data + bytesSent, length - bytesSent, 0);
if (sent == SOCKET_ERROR) return bytesSent;
bytesSent += sent;
}
return bytesSent;
}
int mySocket::send(const char * data_string)
{
return send(data_string, strlen(data_string));
}
private:
SOCKET socketDescriptor;
};
int main()
{
WSAData wsd;
if (WSAStartup(MAKEWORD(2, 2), &wsd) || wsd.wVersion != MAKEWORD(2, 2))
{
WSACleanup();
return 1;
}
//create ze socket
SOCKET socketDescriptor = socket(AF_INET, SOCK_STREAM, 0);
//look up socket info
addrinfo hints;
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
addrinfo *res;
int errCode = getaddrinfo("google.com", "80", &hints, &res);
if (errCode) return 1;
//connect ze socket
int connectStatusCode = ::connect(socketDescriptor, res->ai_addr, res->ai_addrlen);
if (connectStatusCode == SOCKET_ERROR) return 1;
//create zeeeee socket!
mySocket *socket = new mySocket(socketDescriptor);
//prepare ze long data string
int buffSize = 1 * 1000 * 1000 * 1000;
char *buff = new char[buffSize];
memset(buff, 't', buffSize);
buff[buffSize - 3] = '\n';
buff[buffSize - 2] = '\n';
buff[buffSize - 1] = '\0';
//send ze data
int bytesSent = socket->send(buff);
//verify all ze data is sent
bool success = (bytesSent == strlen(buff));
printf("requested bytes = %i\nsent bytes = \t %i", strlen(buff), bytesSent);
printf("\n\nsuccess = %s", success ? "true" : "false");
closesocket(socketDescriptor);
delete socket;
freeaddrinfo(res);
WSACleanup();
getchar();
return 0;
}
编辑3
https://msdn.microsoft.com/en-us/library/windows/desktop/ms740506(v=vs.85).aspx
说明
...
成功完成发送功能不会 表明数据已成功交付并收到 接受者。此功能仅表示数据已成功 的发送
但@Karsten Koop指出了相关行为的类似问题: What is the size of a socket send buffer in Windows? 我很难理解那里有什么东西。但我得到的是它说该函数只是写入缓冲区并返回字节“已发送”。但这不仅意味着它不能保证接收方接收到数据(微软的状态),但这意味着它实际上根本没有发送......只是在缓冲区中。我在这里遗漏了什么,或者微软是否误导了它的行为?
答案 0 :(得分:0)
有多种类型的套接字:Winsock支持多种协议。
仅仅因为socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)
的当前实现通常在所有数据发送之前都会阻塞,但并不意味着其他套接字类型也会阻塞。
此外,如果进程中断,send
可能发送少于完整缓冲区的内容,例如通过网络中断,或者如果套接字从另一端或另一个线程关闭。
此外,Winsock API旨在与BSD和Posix套接字API兼容,如果在呼叫期间收到信号,send
通常会返回错误EINTR
。 (在Unixland中,大多数阻塞调用都可以使用errno==EINTR
返回,这就解决了在单线程系统上处理外部事件的问题。)