[英]Sending and receiving data on a socket in c++
I am currently learning C++ and trying to understand sockets. 我目前正在学习C ++,并试图了解套接字。 I've done sockets before in high level languages in C# and Java but having problems in C++.
我之前已经使用C#和Java的高级语言完成了套接字,但是在C ++中却遇到了问题。
I've gone through the example at https://msdn.microsoft.com/en-us/library/windows/desktop/ms737593(v=vs.85).aspx . 我已经通过https://msdn.microsoft.com/zh-cn/library/windows/desktop/ms737593(v=vs.85).aspx浏览了该示例。
The code I have is pretty much working except there's one thing I'm not sure of. 除了有一件事我不确定之外,我拥有的代码几乎可以正常工作。 When I've written other socket apps, I don't usually receive the response until after a new line character is received.
当我编写其他套接字应用程序时,通常直到收到换行符后才收到响应。
I thought maybe C++ add 1 character received at a time and adds to the buffer, so then when I close the socket, the buffer would contain everything that was received, but it seems to be a hex value, but the hex in an ascii converter seems to print gibberish instead of the socket data. 我以为C ++可能会一次添加一个接收到的字符并添加到缓冲区中,所以当我关闭套接字时,缓冲区将包含接收到的所有内容,但这似乎是一个十六进制值,但是在一个ascii转换器中却是十六进制似乎打印乱码而不是套接字数据。
Below is my code 下面是我的代码
const int DEFAULT_BUF_LEN = 525;
InitialiseLibrary initLibrary("tunnel.conf");
if (initLibrary.initialise(0))
{
cout << "Failed to initialise library" << endl;
}
BitsLibrary bitsLibrary;
StaticSettings staticSettings(&bitsLibrary, "tunnel.conf");
//Open a socket connection
WSAData wsaData;
int iResult;
SOCKET listenSocket = INVALID_SOCKET;
SOCKET clientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSendResult;
char recvBuf[DEFAULT_BUF_LEN];
int recBufLen = DEFAULT_BUF_LEN;
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
cout << "WSAStartup Failed with error: " << iResult << endl;
return EXIT_FAILURE;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
iResult = getaddrinfo(NULL, "500", &hints, &result);
if (iResult != 0)
{
cout << "getaddrinfo failed with error: " << iResult << endl;
return EXIT_FAILURE;
}
listenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (listenSocket == INVALID_SOCKET)
{
cout << "Socket failed with error: " << WSAGetLastError() << endl;
freeaddrinfo(result);
WSACleanup();
return EXIT_FAILURE;
}
iResult = ::bind(listenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult != 0)
{
cout << "bind failed with error: " << iResult << endl;
FreeAddrInfo(result);
closesocket(listenSocket);
WSACleanup();
return EXIT_FAILURE;
}
freeaddrinfo(result);
iResult = listen(listenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR)
{
cout << "Listen failed with error: " << WSAGetLastError() << endl;
closesocket(listenSocket);
WSACleanup();
return EXIT_SUCCESS;
}
sockaddr_in clientAddr;
socklen_t sin_size = sizeof(struct sockaddr_in);
clientSocket = accept(listenSocket, (struct sockaddr*)&clientAddr, &sin_size);
send(clientSocket, "welcome", string("welcome").length(),0);
if (clientSocket == INVALID_SOCKET)
{
cout << "accept failed with error: " << WSAGetLastError() << endl;
closesocket(listenSocket);
WSACleanup();
return EXIT_FAILURE;
}
closesocket(listenSocket);
do {
iResult = recv(clientSocket, recvBuf, recBufLen, 0);
if (iResult > 0)
{
cout << "Bytes received: " << iResult << endl;
cout << "Received: " << recvBuf << endl;
iSendResult = send(clientSocket, recvBuf, iResult, 0);
if (iSendResult == SOCKET_ERROR)
{
cout << "send failed with error: " << WSAGetLastError() << endl;
closesocket(clientSocket);
WSACleanup();
return EXIT_FAILURE;
}
cout << "Bytes sent " << iSendResult << endl;
}
else if (iResult == 0)
{
cout << "Connection closing" << endl;
}
else
{
cout << "Recv failed with error: " << WSAGetLastError() << endl;
closesocket(clientSocket);
WSACleanup();
return EXIT_FAILURE;
}
} while (iResult > 0);
iResult = shutdown(clientSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
cout << "shutdown failed with error: " << WSAGetLastError() << endl;
closesocket(clientSocket);
WSACleanup();
return EXIT_FAILURE;
}
closesocket(clientSocket);
WSACleanup();
cout << "Message was: " << recvBuf << endl;
return EXIT_SUCCESS;
If I'm not mistaken, if I was doing this in C# and connect via telnet to my socket I could send Hello
but the app wouldn't do anything until I sent \\r\\n
or the buffer was full. 如果我没记错的话,如果我在C#中执行此操作并通过telnet连接到我的套接字,则可以发送
Hello
但在发送\\r\\n
或缓冲区已满之前,应用程序不会做任何事情。
However, in my C++ app, as soon as I enter H
my app immediately responds prints out the recvBuf which just contains H
plus a load of blank characters (shows as squares in cmd) which I'm assuming is the blank parts of the array buffer, and sends the reply. 但是,在我的C ++应用程序中,我输入
H
我的应用程序立即响应,打印出recvBuf,其中仅包含H
加上大量空白字符(以cmd表示为正方形),我假设这是数组的空白部分缓冲,并发送答复。
Sockets don't care about newlines or nulls. 套接字不关心换行符或null。 Only higher-level streaming APIs do that.
只有更高级别的流API才能这样做。 The important thing is the return value of
recv()
. 重要的是
recv()
的返回值。 That tells you exactly how many bytes were received. 确切地告诉您接收了多少字节。 Nothing in the buffer beyond that count is valid.
超出该数量的缓冲区中没有任何内容是有效的。
In a streaming protocol, it is useful to establish a protocol for determining the content length. 在流协议中,建立用于确定内容长度的协议是有用的。
For example, a client could send the content-length followed by data and the server would first read the content length and then read the socket in a loop and buffer the data until content-length number of bytes have been received. 例如,客户端可以发送内容长度后跟数据,而服务器将首先读取内容长度,然后循环读取套接字并缓冲数据,直到接收到内容长度字节为止。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.