gpt4 book ai didi

c++ - Winsock 单客户端服务器同时发送和接收

转载 作者:太空狗 更新时间:2023-10-29 20:39:32 25 4
gpt4 key购买 nike

我在使用 C++ 中的简单 Winsock 聊天应用程序时遇到问题。我编写了一段代码,使用户能够选择是要发送数据还是接收数据,并根据用户的选择执行适当的功能。我想要实现的是,用户可以同时发送和接收数据。我怎么能接近它?请注意,我不想使用多个客户端,我只想通过服务器发送和接收数据,同时通过客户端发送和接收数据。

编辑:我添加了我的代码。

#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctime>


int main()
{
string IP;
int userType;

// Ask the user if he is server or client
cout << "Hi, which type of user are you? 1 - Server, 2 - Client" <<endl;
cin >> userType;

// depending on the declared user type, execute the appropriate code
if (userType == 1)
{
//initialize winsock and create a socket
WSAData wsaData; // initialize
iResult = WSAStartup(MAKEWORD(2,1), &wsaData);

if (iResult != NO_ERROR) // check for errors
cout << "Error at WSAStartup()" <<endl;
else
cout << "WSAStartup() is OK." <<endl;

// create socket
sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
if (sockSocket == INVALID_SOCKET) // check for errors
{
cout << "Error at socket(): " << WSAGetLastError();
WSACleanup();
return true;
}
else
cout << "Socket() is OK." <<endl;
return true;

// bind to socket
service.sin_addr.s_addr = inet_addr("0.0.0.0");
service.sin_family = AF_INET;
service.sin_port = htons(55555);

if (bind(sockSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) // cheking for errors
{
cout << "Bind() failed." << endl;
closesocket(sockSocket);
return true;
}
else
cout << "Bind() is OK." <<endl;


// listen
listen(sockSocket, SOMAXCONN);
if (listen(sockSocket, 10) == SOCKET_ERROR) // check for errors
{
cout << "Error listening on socket." << endl;
return true;
}
else
cout << "Listen() is OK." <<endl;

//accept connection
servlen = sizeof(service);
cout << "Waiting for user to connect..." << endl;

acceptSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(acceptSocket = accept(sockSocket, (SOCKADDR*)&service, &servlen))
{
cout << "A coonnection was found" <<endl<<endl;
}
sockSocket = acceptSocket;

// receive messages
do
{
std::string message;
char Buffer[512];
iResult = recv(sockSocket, Buffer, 512, 0);
Buffer[iResult] = '\0';
message = Buffer;
currentDate();
std::cout << Buffer <<endl<<endl;

}while(iResult>0);

closesocket(sockSocket);
WSACleanup();
}

else if (userType == 2)
{
// exactly the same code as for server part to initialize and create socket

// ask for the ip the user wants to connect to
cout << "Hi what's the IP that you want to connect to?" <<endl;
cin >> IP;

// connect to socket
conService.sin_addr.s_addr = inet_addr(IP); // connect to the ipnuted IP
conService.sin_family = AF_INET;
conService.sin_port = htons(55555); // should the port also be the argument?

if (connect(sockSocket, (SOCKADDR*)&conService, sizeof(conService)) == SOCKET_ERROR) // check for errors
{
cout << "Failed to connect: " << WSAGetLastError();
WSACleanup();
return true;
}
else
{
cout << "Connected." <<endl;
}

// send messages
for (;;)
{
std::string message;
std::getline(std::cin, message);
unsigned int Length = strlen(message.c_str());
if(Length>512)
Length = 512;
currentDate();
iResult = send(sockSocket, message.c_str(),Length,0);
}
closesocket(sockSocket);
WSACleanup();
}

WSACleanup();
return 0;
}

Edit2:正如 Lemy 在评论中建议的那样,我需要有第二个线程(因为第一个线程只是 main 函数中发生的事情)。据我了解,我可以使用 CreateThread 函数。我如何发送和接收消息的问题已经解决(我应该创建另一个线程),但现在我在实现解决方案时遇到了问题。正如我在 Lemy 的回答下方的评论中所写的那样,我在使用 CreateThread 函数的那一行得到了这样的错误 (HANDLE hThread = CreateThread(0,0,&ReadingThread,acceptSocket,0,&dwThreadID);):

  1. 从“SOCKET {aka unsigned int}”到“PVOID {aka void*}”的无效转换 [-fpermissive]|和
  2. 从“DWORD {aka long unsigned int}”到“PDWORD {aka long unsigned int*}”的无效转换 [-fpermissive]

有什么提示吗?希望这能让我的问题更具体(如果不是请告诉我我应该具体说明什么)。

最佳答案

您需要让客户端和服务器在连接的生命周期内不断地在后台读取数据,然后它们可以在需要时并行发送数据。将您的阅读逻辑移至单独的线程中,例如:

#include <WinSock2.h>
#include <Windows.h>
#include <iostream>
#include <string>
#include <stdio.h>
#include <ctime>

DWORD WINAPI ReadingThread(LPVOID param)
{
SOCKET s = (SOCKET) param;
char Buffer[512];
int iResult;

do
{
iResult = recv(s, Buffer, 512, 0);
if (iResult <= 0) break;
Buffer[iResult] = '\0';
std::cout << "Recv: " << message << std::endl;
}
while (true);

return 0;
}

int main()
{
int userType;
HANDLE hThread;
DWORD dwThreadID;

//initialize winsock and create a socket
WSAData wsaData; // initialize
iResult = WSAStartup(MAKEWORD(2,1), &wsaData);

if (iResult != NO_ERROR) // check for errors
{
std::cout << "Error at WSAStartup()" << std::endl;
return 0;
}

std::cout << "WSAStartup() is OK." << std::endl;

// Ask the user if he is server or client
std::cout << "Hi, which type of user are you? 1 - Server, 2 - Client" << std::endl;
std::cin >> userType;

// depending on the declared user type, execute the appropriate code
if (userType == 1)
{
// create socket
sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
if (sockSocket == INVALID_SOCKET) // check for errors
{
std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
WSACleanup();
return 0;
}

std::cout << "Socket() is OK." << std::endl;

// bind to socket
service.sin_addr.s_addr = INADDR_ANY;
service.sin_family = AF_INET;
service.sin_port = htons(55555);

if (bind(sockSocket, (SOCKADDR*)&service, sizeof(service)) == SOCKET_ERROR) // cheking for errors
{
std::cout << "Error at bind(): " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}

std::cout << "Bind() is OK." << std::endl;

// listen
if (listen(sockSocket, 10) == SOCKET_ERROR) // check for errors
{
std::cout << "Error at listen(): " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}

std::cout << "Listen() is OK." << std::endl;

//accept connection
servlen = sizeof(service);
std::cout << "Waiting for user to connect..." << std::endl;

acceptSocket = accept(sockSocket, (SOCKADDR*)&service, &servlen);
if (acceptSocket != INVALID_SOCKET)
{
std::cout << "Error at accept(): " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}

std::cout << "A client has connected" << std::endl << std::endl;

// receive messages
hThread = CreateThread(NULL, 0, &ReadingThread, (void*)acceptSocket, 0, &dwThreadID);
if (!hThread)
{
std::cout << "Error at CreateThread(): " << GetLastError() << std::endl;
closesocket(acceptSocket);
closesocket(sockSocket);
WSACleanup();
return 0;
}

// send messages
do
{
std::string message;
if (!std::getline(std::cin, message))
break;

if (send(acceptSocket, msg.c_str(), msg.length(), 0) == SOCKET_ERROR)
{
std::cout << "Error at send(): " << WSAGetLastError() << std::endl;
break;
}
}
while (true);

closesocket(acceptSocket);

WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);

closesocket(sockSocket);
WSACleanup();
}

else if (userType == 2)
{
// create socket
sockSocket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); // create a socket
if (sockSocket == INVALID_SOCKET) // check for errors
{
std::cout << "Error at socket(): " << WSAGetLastError() << std::endl;
WSACleanup();
return 0;
}

std::cout << "Socket() is OK." << std::endl;

// ask for the ip the user wants to connect to
std::string IP;
std::cout << "Hi what's the IP that you want to connect to?" << std::endl;
std::cin >> IP;

// connect to socket
conService.sin_addr.s_addr = inet_addr(IP.c_str()); // connect to the ipnuted IP
conService.sin_family = AF_INET;
conService.sin_port = htons(55555); // should the port also be the argument?

if (connect(sockSocket, (SOCKADDR*)&conService, sizeof(conService)) == SOCKET_ERROR) // check for errors
{
std::cout << "Failed to connect: " << WSAGetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}

std::cout << "Connected." << std::endl;

// receive messages
hThread = CreateThread(NULL, 0, &ReadingThread, (void*)sockSocket, 0, &dwThreadID);
if (!hThread)
{
std::cout << "Error at CreateThread(): " << GetLastError() << std::endl;
closesocket(sockSocket);
WSACleanup();
return 0;
}

// send messages
do
{
std::string message;
if (!std::getline(std::cin, message))
break;

if (send(sockSocket, msg.c_str(), msg.length(), 0) == SOCKET_ERROR)
{
std::cout << "Error at send(): " << WSAGetLastError() << std::endl;
break;
}
}
while (true);

closesocket(sockSocket);

WaitForSingleObject(hThread, INFINITE);
CloseHandle(hThread);

WSACleanup();
}

else
{
std::cout << "Invalid type entered!" << std::endl;
WSACleanup();
return 0;
}

return 0;
}

关于c++ - Winsock 单客户端服务器同时发送和接收,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27610316/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com