我用 C++ 编写了一个服务器程序,也用 C++ 编写了一个客户端程序。两者都工作正常,但是当一个客户端与服务器通信时,其他客户端无法连接到同一台服务器。如果假设当我关闭客户端 1 时,那么我的第二个客户端也无法连接到服务器。我已经用多个线程启动了我的服务器以连接到多个客户端,但只有一个客户端正在连接。
我的服务器程序:
#include <iostream>
#include <winsock2.h>
#include <Windows.h>
#include <process.h>
#include <thread>
#pragma comment(lib,"ws2_32.lib")
static const int num_of_threads = 2;
void client_disconnected(SOCKET Socket);
void start_server()
{
WSADATA WsaDat;
if(WSAStartup(MAKEWORD(2,2),&WsaDat)!=0)
{
std::cout<<"WSA Initialization failed!\r\n";
WSACleanup();
system("PAUSE");
}
SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(Socket==INVALID_SOCKET)
{
std::cout<<"Socket creation failed.\r\n";
WSACleanup();
system("PAUSE");
}
SOCKADDR_IN serverInf;
serverInf.sin_family=AF_INET;
serverInf.sin_addr.s_addr=INADDR_ANY;
serverInf.sin_port=htons(8888);
if(bind(Socket,(SOCKADDR*)(&serverInf),sizeof(serverInf))==SOCKET_ERROR)
{
std::cout<<"Unable to bind socket!\r\n";
WSACleanup();
system("PAUSE");
}
listen(Socket,3);
SOCKET TempSock=SOCKET_ERROR;
while(TempSock==SOCKET_ERROR)
{
std::cout<<"Waiting for incoming connections...\r\n";
Sleep(5000);
TempSock=accept(Socket,NULL,NULL);
}
// If iMode!=0, non-blocking mode is enabled.
u_long iMode=1;
ioctlsocket(Socket,FIONBIO,&iMode);
Socket=TempSock;
std::cout<<"Client connected!\r\n\r\n";
// Main loop
for(;;)
{
int nError=WSAGetLastError();
if(nError!=WSAEWOULDBLOCK&&nError!=0)
{
client_disconnected(Socket);
break;
}
char *szMessage="Welcome to the server!\r\n";
send(Socket,szMessage,strlen(szMessage),0);
Sleep(2000);
}
}
void client_disconnected(SOCKET Socket)
{
std::cout<<"Client disconnected!\r\n";
// Shutdown our socket
shutdown(Socket,SD_SEND);
// Close our socket entirely
closesocket(Socket);
WSACleanup();
}
int main()
{
//starting multiple threads for invoking server
std::thread threads[num_of_threads];
//This statement will launch multiple threads in loop
for (int i = 0; i < num_of_threads; ++i) {
threads[i] = std::thread(start_server);
Sleep(2000);
}
for (int i = 0; i < num_of_threads; ++i) {
threads[i].join();
}
return 0;
}
我的客户程序:
#include <iostream>
#include <winsock2.h>
#include <Windows.h>
#include <process.h>
#include "client.h"
#pragma comment(lib,"ws2_32.lib")
void MultipleClient :: receiveToClient(void*data)
{
WSADATA WsaDat;
if(WSAStartup(MAKEWORD(2,2),&WsaDat)!=0)
{
std::cout<<"Winsock error - Winsock initialization failed\r\n";
WSACleanup();
system("PAUSE");
}
// Create our socket
SOCKET Socket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(Socket==INVALID_SOCKET)
{
std::cout<<"Winsock error - Socket creation Failed!\r\n";
WSACleanup();
system("PAUSE");
}
// Resolve IP address for hostname
struct hostent *host;
if((host=gethostbyname("localhost"))==NULL)
{
std::cout<<"Failed to resolve hostname.\r\n";
WSACleanup();
system("PAUSE");
}
// Setup our socket address structure
SOCKADDR_IN SockAddr;
SockAddr.sin_port=htons(8888);
SockAddr.sin_family=AF_INET;
SockAddr.sin_addr.s_addr=*((unsigned long*)host->h_addr);
// Attempt to connect to server
if(connect(Socket,(SOCKADDR*)(&SockAddr),sizeof(SockAddr))!=0)
{
std::cout<<"Failed to establish connection with server\r\n";
WSACleanup();
system("PAUSE");
}
// If iMode!=0, non-blocking mode is enabled.
u_long iMode=1;
ioctlsocket(Socket,FIONBIO,&iMode);
// Main loop
for(;;)
{
// Display message from server
char buffer[1000];
memset(buffer,0,999);
int inDataLength=recv(Socket,buffer,1000,0);
std::cout<<buffer;
//end client when server is disconnected
int nError=WSAGetLastError();
if(nError!=WSAEWOULDBLOCK&&nError!=0)
{
std::cout<<"Winsock error code: "<<nError<<"\r\n";
std::cout<<"Server disconnected!\r\n";
// Shutdown our socket
shutdown(Socket,SD_SEND);
// Close our socket entirely
closesocket(Socket);
break;
}
Sleep(2000);
}
WSACleanup();
system("PAUSE");
}
class Client{
public:
static unsigned int __stdcall receiveMessageThread(void *p_this)
{
MultipleClient* mc = static_cast<MultipleClient*>(p_this);
mc-> receiveToClient(p_this); // Non-static member function!
return 0;
}
void startThread()
{
HANDLE myhandleA;
myhandleA = (HANDLE)_beginthreadex(0,0,&Client::receiveMessageThread,this,0, 0);
WaitForSingleObject(myhandleA, INFINITE);
}
};
int main(void)
{
Client *c = new Client;
c->startThread();
return 0;
}
请帮助我如何使多个客户端与单个服务器连接。示例代码将非常有用(对不起,问)。
您在线程之间分配工作的方式是错误的。
您希望有一个线程打开侦听套接字并等待那里的传入连接。请注意,每个端口不能有多个侦听套接字,因此您绝对不希望多个线程同时尝试侦听同一个端口。
如果一个连接进来,accept
会给你一个新的套接字对象。您仍然拥有等待新连接的原始侦听套接字,但您现在还有第二个套接字,其中已建立与客户端的连接。
现在您可以拆分工作:让一个线程返回调用listen
原始套接字并等待新连接,而另一个线程获取新套接字并执行必要的 I/O 以与客户端交互。
在这个简单的方案中,每个客户端连接总是有一个线程,另外还有一个用于侦听套接字的线程。由于所有这些线程都将花费大量时间来等待网络 I/O 完成,因此您可以使用异步 I/O 在较少(甚至单个)线程之间共享工作负载,但这稍微复杂一些完成,所以我建议你把它留到第二稿。
本文收集自互联网,转载请注明来源。
如有侵权,请联系 [email protected] 删除。
我来说两句