使套接字服务器接受多个客户端
Make socket server accept multiple clients
我想改变我正在使用的套接字类来接受无限数量的客户端。目前它只允许一个客户端连接,一旦客户端断开连接,服务器就退出。
#include "stdafx.h"
#include "mySocket.h"
#include "myException.h"
#include "myHostInfo.h"
void main()
{
#ifdef WINDOWS_XP
// Initialize the winsock library
WSADATA wsaData;
try
{
if (WSAStartup(0x101, &wsaData))
{
myException* initializationException = new myException(0,"Error: calling WSAStartup()");
throw initializationException;
}
}
catch(myException* excp)
{
excp->response();
delete excp;
exit(1);
}
#endif
// get local server information
myHostInfo uHostAddress;
string localHostName = uHostAddress.getHostName();
string localHostAddr = uHostAddress.getHostIPAddress();
cout << "------------------------------------------------------" << endl;
cout << " My local host information:" << endl;
cout << " Name: " << localHostName << endl;
cout << " Address: " << localHostAddr << endl;
cout << "------------------------------------------------------" << endl;
// open socket on the local host
myTcpSocket myServer(PORTNUM);
cout << myServer;
myServer.bindSocket();
cout << endl << "server finishes binding process... " << endl;
myServer.listenToClient();
cout << "server is listening to the port ... " << endl;
// wait to accept a client connection.
// processing is suspended until the client connects
cout << "server is waiting for client connecction ... " << endl;
myTcpSocket* client; // connection dedicated for client communication
string clientHost; // client name etc.
client = myServer.acceptClient(clientHost);
cout << endl << "==> A client from [" << clientHost << "] is connected!" << endl << endl;
while(1)
{
//Send message to the client
client->sendMessage(std::string("Test"));
// receive from the client
string clientMessageIn = "";
int numBytes = client->recieveMessage(clientMessageIn); //Get message from client, non-blocking using select()
if ( numBytes == -99 ) break;
if(clientMessageIn != "")
{
std::cout << "received: " << clientMessageIn << std::endl; //What did we receive?
/* Do somethign with message received here */
}
}
#ifdef WINDOWS_XP
// Close the winsock library
try
{
if (WSACleanup())
{
myException* cleanupException = new myException(0,"Error: calling WSACleanup()");
throw cleanupException;
}
}
catch(myException* excp)
{
excp->response();
delete excp;
exit(1);
}
#endif
}
我如何改变main()函数,使它不断等待新的客户端连接,一旦他们做了,为他创建一个新的线程(客户端),或一个新的处理程序套接字(无论可能是什么)。
我确实发现这个线程很有用,但是我缺乏在上面的代码中实际实现它所需的套接字知识。
答案是When doing socket communication, you basically have a single listener socket for all incoming connections, and multiple handler sockets for each connected client.
所以我猜在我的代码;
myTcpSocket myServer(PORTNUM);
myServer.bindSocket();
myServer.listenToClient();
就是listener socket
但是我在哪里/如何分叉连接到handler socket
的客户端?
这个想法很简单,您只需等待传入的连接,一旦接受,将套接字传递给线程。
您需要将accept
返回的新套接字传递给新线程;您可以每次生成一个新线程并通过参数传递套接字,或者将套接字添加到一堆工作线程使用的共享队列中。
这是我写的一个简单代理的一些代码,它使用boost的线程和一个简单的面向对象封装套接字函数。
主线程-它创建了4个空闲的工作线程并等待要发出信号的信号量。它将所有接受的连接推送到全局队列:
// Global variables
const size_t MAX_THREADS = 4;
queue<Socket> socketBuffer; // Holds new accepted sockets
boost::mutex queueGuard; // Guards the socketBuffer queue
semaphore queueIndicator; // Signals a new connection to the worker threads
bool ctrlc_pressed = false;
// Inside the main function...
boost::thread_group threads;
for(int i = 0; i < MAX_THREADS; i++)
{
threads.create_thread(boost::bind(&threadHandleRequest, i+1));
}
while(!ctrlc_pressed)
{
// wait for incoming connections and pass them to the worker threads
Socket s_connection = s_server.accept();
if(s_connection.valid())
{
boost::unique_lock<boost::mutex> lock(queueGuard);
socketBuffer.push(s_connection);
queueIndicator.signal();
}
}
threads.interrupt_all(); // interrupt the threads (at queueGuard.wait())
threads.join_all(); // wait for all threads to finish
s_server.close();
和线程代码:
bool threadHandleRequest(int tid)
{
while(true)
{
// wait for a semaphore counter > 0 and automatically decrease the counter
try
{
queueIndicator.wait();
}
catch (boost::thread_interrupted)
{
return false;
}
boost::unique_lock<boost::mutex> lock(queueGuard);
assert(!socketBuffer.empty());
Socket s_client = socketBuffer.front();
socketBuffer.pop();
lock.unlock();
// Do whatever you need to do with the socket here
}
}
希望有帮助
在进行套接字通信时,基本上只有一个侦听器的多个处理程序套接字每个连接的客户端。
这才是重点。侦听器套接字需要一个单独的线程。当它接收到一个传入请求时,它为一个处理程序套接字启动另一个线程(它将创建并发送响应),并再次开始侦听(您需要一个循环)。
我肯定会使用线程而不是分叉。据我所知,在Windows上只有cygwin能够分叉,但我不会在这样的程序中使用cygwin。
- 在 1 个服务器 n 客户端套接字 C++ MFC 应用程序中更新数据的客户端
- TCP 服务器的异步读取使用 boost::asio 打印客户端套接字发送的数据
- 我正在编写一个简单的客户端套接字应用程序,但在连接后服务器收到一个空缓冲区
- 防止客户端套接字程序崩溃CPP Google Protobuf
- 为什么在此 UDP 客户端/服务器示例中没有必要绑定客户端套接字?
- 客户端套接字是可绑定的,但不可连接,因为已在使用中
- 是否可以寻址另一个网络中的服务器/客户端套接字?(C++)
- 关闭客户端套接字时如何防止服务器关闭?C++
- 多连接客户端套接字应用程序C++
- C 选择仅检查最后一个客户端套接字
- 在两个客户端套接字之间发送数据
- Qt 5: 如何制作"pure c++"客户端套接字?
- Winsock 客户端套接字无效
- C++面向对象的客户端套接字应用程序设计
- 如何强制 udp 服务器接收的 udp 客户端套接字绑定到特定客户端端口
- 客户端套接字连接() 在服务器 accept() 超时后成功
- 如果客户端的互联网断开连接,客户端套接字不会关闭。如何在服务器中检测此事件?
- 客户端套接字在c++中发送到服务器
- 服务器和客户端套接字连接问题重新。send(), accept() 和多线程
- 使用c++ TCP客户端套接字在特定的网络接口Linux/Unix