WinSock 2.2 send()関数は常に私に送信したいすべてのバイトを返します!私はポート80でgoogle.comに接続し、データのためにランダムにt
文字を送信しています。私もt
の1GBのものを送信しようとしました。それはまだ送信されたすべてのバイトで返されます。パケットに収まるバイト数と、実装のwhileループで処理される残りのバイト数を返すことを期待していましたが、結果としてwhileループの中に入ることはありませんでした。WinSock 2.2 TCP/IPv4 send()は常に送信されたすべてのバイトを返します
私はTCP/IPv4ソケットを使用しています。私は私のインターネットが私が点滅することができるよりも速く1GBを送るために速く点灯していないことを知っている。
このコードは、最も重要なチャンクについて示されています。例えば、私が示したsendを呼び出すC-string send呼び出しのラッパーは省略されています。それがここの人々を混乱させるために始めたので、テストコード
//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));
を呼び出す
はimplementatian
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;
}
EDIT 1
を送るラッパー
です送るラッパー
int mySocket::send(const char * data_string)
{
return send(dataString, strlen(data_string));
}
EDITここ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;
}
EDIT 3
https://msdn.microsoft.com/en-us/library/windows/desktop/ms740506(v=vs.85).aspx
備考
...
正常に完了はありませんは、データが正常に配信され、受信者 に受信されたことを示します。この機能は、 を送信した場合にのみと表示されます。私はひどくそこwrittentているものを理解し What is the size of a socket send buffer in Windows? :
しかし@Karstenクープは、関連する行動上の同様の問題を指摘しました。しかし、私が得たことは、関数が単にバッファに書き込んで、 "送信済みの"バイトを返すということです。これは受信者がデータを受け取ったことを保証していないことを意味するだけでなく(実際にはまったく送信されないことを意味します)、バッファ内にあります。私はここで何かを見逃しているのですか、またはその動作について誤解を招くマイクロソフトですか?
'int bytesSent = socket-> send(buff);'長さを指定するのを忘れました。これはおそらく0として満たされていたので、コンパイラはバッファを最適化しました(使用したことがないため)。長さを過ぎてみてください。おそらく動作しますか? – LambdaBeta
'socket-> send(buff、strlen(buff));' – Raindrop7
@LambdaBeta no。そのためのラッパーがあります。私はそれに質問を更新しています。 – Infogeek