在窗口的多個客戶端連接到單個服務器我已經寫了客戶端和服務器在C++,可以處理多個客戶端程序。現在的問題是:多線程在C++
我在服務器的main()函數中啓動了兩個線程,以便一個線程監聽(打開)與客戶端的連接,另一個線程接受連接並將數據發送到連接的客戶端。這兩個線程都定期運行(即連續)。
現在,當我連接的客戶機1向服務器的客戶端1接收的同時另一個客戶端2連接到然後客戶機1將進入等待狀態和客戶端2得到的數據的服務器的信息和時。現在,當我關閉客戶端2時,服務器顯示我兩個客戶端都斷開連接,但客戶端1正在運行,因爲它處於無限循環中,並且由於線程將定期運行,服務器將再次開始監聽並再次接受連接。這會與client1建立新的連接,並且客戶端1正在接收數據。
誰能幫我消除這種。我需要同時將數據發送到連接到服務器,當任何客戶端斷開,不應該影響其他客戶端的客戶端數量。一個可以處理多個客戶端的簡單服務器。
我的服務器程序:
#include <iostream>
#include <winsock2.h>
#include <Windows.h>
#include <process.h>
#include <thread>
#pragma comment(lib,"ws2_32.lib")
static int flag = 0;
BOOL bOptVal = FALSE;
WSADATA WsaDat;
SOCKET Socket;
std:: thread t1,t2,t3;
void client_disconnected(SOCKET Socket);
void startThreads();
void timer_start(std::function<void(void)> func, unsigned int interval);
void accept_connection();
void send_message();
void start_server_listening()
{
if(WSAStartup(MAKEWORD(2,2),&WsaDat)!=0)
{
std::cout<<"WSA Initialization failed!\r\n";
WSACleanup();
system("PAUSE");
}
Socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if (setsockopt(Socket, SOL_SOCKET, SO_REUSEADDR, (char *) &bOptVal, sizeof(bOptVal)) < 0) {
perror("setsockopt(SO_REUSEADDR) failed");
exit(EXIT_FAILURE);
}
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");
}
else{
listen(Socket,3);
accept_connection();
}
}
void accept_connection()
{
SOCKET TempSock=SOCKET_ERROR;
while(TempSock==SOCKET_ERROR)
{
std::cout<<"\nWaiting for incoming connections\n";
Sleep(2000);
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";
send_message();
if(flag==1){
Sleep(1000);
//system("PAUSE");
}
}
void send_message()
{
for(;;)
{
int nError=WSAGetLastError();
if(nError!=WSAEWOULDBLOCK&&nError!=0)
{
flag=1;
client_disconnected(Socket);
break;
}
else {
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()
{
// start a timer that executes threads periodically/continuously
timer_start(startThreads, 200); //calling timer function
while(true);
return 0;
}
void timer_start(std::function<void(void)> func, unsigned int interval)
{
std::thread([func, interval]() { // calling startThreads() function
while (true)
{
func();
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
}
}).detach();
}
void startThreads()
{
//starting two threads one starts listening and other accepts connections
t1 = std::thread(start_server_listening);
t2 = std:: thread(accept_connection);
t1.join();
t2.join();
}
我的客戶端程序:
#include <iostream>
#include <winsock2.h>
#include <Windows.h>
#include <process.h>
#include <thread>
#pragma comment(lib,"ws2_32.lib")
void startThreads();
void timer_start(std::function<void(void)> func, unsigned int interval);
std:: thread t1;
void receiveToClient()
{
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 = inet_addr("127.0.0.1");
// 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(;;)
{
int nError=WSAGetLastError();
if(nError!=WSAEWOULDBLOCK&&nError!=0)
break;
// 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
Sleep(2000);
}
WSACleanup();
}
int main()
{
timer_start(startThreads, 200);
while(true);
return 0;
}
void timer_start(std::function<void(void)> func, unsigned int interval)
{
std::thread([func, interval]() {
while (true)
{
func();
std::this_thread::sleep_for(std::chrono::milliseconds(interval));
}
}).detach();
}
void startThreads()
{
t1 = std::thread(receiveToClient);
t1.join();
}
The while(true);在主循環只保證你的程序將**從不**退出。對於連接處理,我將使用一個受互斥鎖保護的向量來存儲每個連接,並編寫一個函數,檢查連接是否打開,如果沒有連接,請將其刪除。 – JeremiahB