【发布时间】:2020-10-09 23:42:13
【问题描述】:
我想编写一个客户端/服务器应用程序,客户端和服务器可以在其中交换消息。
Client site communication:
send
recv
send
recv
Server site communication:
recv
send
recv
send
但是,我有一个问题,因为只有一条消息是发送/接收。之后,套接字关闭,不再发送更多消息。出了什么问题以及如何解决这个问题?谢谢。
服务器代码:
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_PORT "27501"
#define SIZE 1024
int SendAllToClient(SOCKET ClientSocket, char *buffer)
{
int iSendResult;
int total = 0, len = 1024;
int bytesleft = 1024;
while( total < len )
{
iSendResult = send( ClientSocket, buffer, 1024, NULL);
if (iSendResult == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
total += iSendResult;
bytesleft -= iSendResult;
}
printf("Bytes sent: %d\n", iSendResult);
return total<len?- 1: 1;
}
char *ReadFromClient(SOCKET ConnectSocket)
{
int iResult;
char *buffer = new char[1024];
memset(buffer, 0, 1024);
do
{
iResult = recv(ConnectSocket, buffer, 1024, 0);
if ( iResult > 0 )
printf("Bytes received: %d\n", iResult);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
}
while( iResult > 0 );
return buffer;
}
int main(int argc , char *argv[])
{
WSADATA wsaData;
char *buffer;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int sessionID;
int iResult;
// Datagram d1,d2,d3;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 )
{
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET)
{
printf("socket failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR)
{
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
printf("Server is listening on localhost:%s ...\n", DEFAULT_PORT);
// Accept a client socket
SOCKADDR_IN addr;
int addrlen = sizeof(addr);
ClientSocket = accept(ListenSocket, (SOCKADDR*)&addr, &addrlen);
if (ClientSocket == INVALID_SOCKET)
{
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
char *ip = inet_ntoa(addr.sin_addr);
int port = addr.sin_port;
printf("\nClient %s:%d connected to server\n", ip, port);
// No longer need server socket
closesocket(ListenSocket);
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//read
buffer = ReadFromClient(ClientSocket);
printf("FROM CLIENT: %s\n", buffer);
//send
memset(buffer, 0, 1024);
memcpy(buffer, "Hi client, how are you?", strlen("Hi client, how are you?"));
SendAllToClient(ClientSocket, buffer);
//read
//send
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
客户端代码:
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_PORT "27501"
#define SIZE 1024
int SendAllToServer(SOCKET ServerSocket, char *buffer)
{
int iSendResult;
int total = 0, len = 1024;
int bytesleft = 1024;
while( total < len )
{
iSendResult = send( ServerSocket, buffer, 1024, NULL);
if (iSendResult == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ServerSocket);
WSACleanup();
return 1;
}
total += iSendResult;
bytesleft -= iSendResult;
}
printf("Bytes sent: %d\n", iSendResult);
return total<len?- 1: 1;
}
char *ReadFromServer(SOCKET ConnectSocket)
{
int iResult;
char *buffer = new char[1024];
memset(buffer, 0, 1024);
do {
iResult = recv(ConnectSocket, buffer, 1024, 0);
if ( iResult > 0 )
printf("Bytes received: %d\n", iResult);
else if ( iResult == 0 )
printf("Connection closed\n");
else
printf("recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
return buffer;
}
int main(int argc , char *argv[])
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char* buffer;
int sessionID;
int iResult;
// Datagram d1,d2;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo("127.0.0.1", DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
//send
buffer = new char[1024];
memset(buffer, 0, 1024);
memcpy(buffer, "Hi server", strlen("Hi server"));
SendAllToServer(ConnectSocket, buffer);
//read
memset(buffer, 0, 1024);
buffer = ReadFromServer(ConnectSocket);
printf("FROM SERVER: %s\n", buffer);
//send
//read
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
编辑
服务器
#include "data_types.h"
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_PORT "27015"
#define SIZE 1024
int SendAllToClient(SOCKET ClientSocket)
{
char *buffer = new char[SIZE];
int iSendResult;
memset(buffer, 0, SIZE);
int total = 0, len = SIZE;
int bytesleft = SIZE;
while( total < len )
{
iSendResult = send( ClientSocket, buffer + total, bytesleft, NULL);
if (iSendResult == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
total += iSendResult;
bytesleft -= iSendResult;
}
printf("Bytes sent: %d\n", iSendResult);
delete buffer;
return total<len?- 1: 1;
}
char* ReadFromClient(SOCKET ClientSocket)
{
std::string data = "";
char *all = NULL;
char buffer[1];
int total = 0, len = SIZE;
int bytesleft = SIZE;
int iResult;
memset(buffer, 0, 1);
while(total < len)
{
if ((iResult = recv(ClientSocket, buffer, 1, 0)) == 0)
{
if (errno != 0)
{
// cleanup
closesocket(ClientSocket);
WSACleanup();
exit(1);
}
}
data = data + std::string(buffer);
total += iResult;
bytesleft -= iResult;
memset(buffer, 0, 1);
}
all = new char[data.length() + 1];
strcpy(all, data.c_str());
return all;
}
int main(int argc , char *argv[])
{
WSADATA wsaData;
char *buffer;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int sessionID;
int iResult;
// Datagram d1,d2,d3;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory(&hints, sizeof(hints));
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
// Resolve the server address and port
iResult = getaddrinfo(NULL, DEFAULT_PORT, &hints, &result);
if ( iResult != 0 )
{
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Create a SOCKET for connecting to server
ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
if (ListenSocket == INVALID_SOCKET)
{
printf("socket failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
WSACleanup();
return 1;
}
// Setup the TCP listening socket
iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
if (iResult == SOCKET_ERROR)
{
printf("bind failed with error: %d\n", WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
iResult = listen(ListenSocket, SOMAXCONN);
if (iResult == SOCKET_ERROR)
{
printf("listen failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
printf("Server is listening on localhost:%s ...\n", DEFAULT_PORT);
// Accept a client socket
SOCKADDR_IN addr;
int addrlen = sizeof(addr);
ClientSocket = accept(ListenSocket, (SOCKADDR*)&addr, &addrlen);
if (ClientSocket == INVALID_SOCKET)
{
printf("accept failed with error: %d\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
char *ip = inet_ntoa(addr.sin_addr);
int port = addr.sin_port;
printf("\nClient %s:%d connected to server\n", ip, port);
// No longer need server socket
closesocket(ListenSocket);
// shutdown the connection since we're done
iResult = shutdown(ClientSocket, SD_SEND);
if (iResult == SOCKET_ERROR)
{
printf("shutdown failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//read
buffer = new char[1024];
memset(buffer, 0, 1024);
buffer = ReadFromClient(ClientSocket);
printf("FROM CLIENT: %s\n", buffer);
//send
memset(buffer, 0, 1024);
memcpy(buffer, "Hi client, how are you?", strlen("Hi client, how are you?"));
// Send an initial buffer
iResult = send( ClientSocket, buffer, (int)strlen(buffer), 0 );
if (iResult == SOCKET_ERROR) {
wprintf(L"send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//read
//send
// cleanup
closesocket(ClientSocket);
WSACleanup();
return 0;
}
客户
#include "data_types.h"
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdlib.h>
#include <stdio.h>
#include <string>
#include <iostream>
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_PORT "27015"
#define SIZE 1024
int SendAllToServer(SOCKET ClientSocket)
{
char *buffer = new char[SIZE];
memset(buffer, 0, SIZE);
int total = 0, len = SIZE;
int bytesleft = SIZE, iSendResult;
while( total < len )
{
iSendResult = send( ClientSocket, buffer + total, bytesleft, NULL);
if (iSendResult == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
total += iSendResult;
bytesleft -= iSendResult;
}
printf("Bytes sent: %d\n", iSendResult);
delete buffer;
return total<len?- 1: 1;
}
char *ReadFromServer(SOCKET ClientSocket)
{
std::string data = "";
char *all = NULL;
char buffer[1];
int total = 0, len = SIZE;
int bytesleft = SIZE;
int iResult;
memset(buffer, 0, 1);
while(total < len)
{
if ((iResult = recv(ClientSocket, buffer, 1, 0)) == 0)
{
if (errno != 0)
{
// cleanup
closesocket(ClientSocket);
WSACleanup();
exit(1);
}
}
data = data + std::string(buffer);
total += iResult;
bytesleft -= iResult;
memset(buffer, 0, 1);
}
all = new char[data.length() + 1];
strcpy(all, data.c_str());
return all;
}
int main(int argc , char *argv[])
{
WSADATA wsaData;
SOCKET ConnectSocket = INVALID_SOCKET;
struct addrinfo *result = NULL,
*ptr = NULL,
hints;
char* buffer;
int sessionID;
int iResult;
// Datagram d1,d2;
// Initialize Winsock
iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
if (iResult != 0) {
printf("WSAStartup failed with error: %d\n", iResult);
return 1;
}
ZeroMemory( &hints, sizeof(hints) );
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
// Resolve the server address and port
iResult = getaddrinfo("127.0.0.1", DEFAULT_PORT, &hints, &result);
if ( iResult != 0 ) {
printf("getaddrinfo failed with error: %d\n", iResult);
WSACleanup();
return 1;
}
// Attempt to connect to an address until one succeeds
for(ptr=result; ptr != NULL ;ptr=ptr->ai_next) {
// Create a SOCKET for connecting to server
ConnectSocket = socket(ptr->ai_family, ptr->ai_socktype,
ptr->ai_protocol);
if (ConnectSocket == INVALID_SOCKET) {
printf("socket failed with error: %d\n", WSAGetLastError());
WSACleanup();
return 1;
}
// Connect to server.
iResult = connect( ConnectSocket, ptr->ai_addr, (int)ptr->ai_addrlen);
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
ConnectSocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if (ConnectSocket == INVALID_SOCKET) {
printf("Unable to connect to server!\n");
WSACleanup();
return 1;
}
//send
buffer = new char[1024];
memset(buffer, 0, 1024);
memcpy(buffer, "Hi server, how are you?", strlen("Hi server, how are you?"));
// Send an initial buffer
iResult = send( ConnectSocket, buffer, (int)strlen(buffer), 0 );
if (iResult == SOCKET_ERROR) {
closesocket(ConnectSocket);
WSACleanup();
return 1;
}
//read
memset(buffer, 0, 1024);
// Receive until the peer closes the connection
do {
iResult = recv(ConnectSocket, buffer, 1024, 0);
if ( iResult > 0 )
wprintf(L"Bytes received: %d\n", iResult);
else if ( iResult == 0 )
wprintf(L"Connection closed\n");
else
wprintf(L"recv failed with error: %d\n", WSAGetLastError());
} while( iResult > 0 );
printf("FROM SERVER: %s\n", buffer);
//send
//read
// cleanup
closesocket(ConnectSocket);
WSACleanup();
return 0;
}
【问题讨论】:
-
您能否将您的手指指向您声称的应该在发送和接收之间循环的实际代码行?在任何地方都找不到这样的代码行。此外,在处理部分发送和接收方面,发送和接收功能都被完全破坏了。
ReadFromServer未能完全实现。SendAllToServer努力更新total和bytesleft,但未能更新buffer,因此部分发送的消息将导致它再次重新发送消息的开头。您也需要解决这些问题。 -
最后,socket的两边都由同一个进程处理。尽管您的操作系统套接字缓冲区很可能足够大,可以在内部缓冲 1024 字节,但您无法保证这种效果,因此显示的代码最终可能会自行死锁。
-
@SamVarshavchik:但是,如果这些功能能够正确实现,是否有可能实现这样的通信?
-
当然,在 C++ 中一切皆有可能。
-
Stackoverflow.com 并不是一个真正的 C++ 教程网站,但这就是你做这件事的方式。只需拿出一张白纸。用简单的英语用简短、简单的句子写下一个逐步的过程。完成后,call your rubber duck for an appointment。在您的橡皮鸭批准您提出的行动计划后,只需将您写下的内容直接翻译成 C++。任务完成!
标签: c++ winsock send winsock2 recv