如何在多线程客户机的多个线程上访问同一个套接字
How to access same socket on multiple threads for multi-threaded client
我有一个多线程客户机,它的设置是为了在一个线程上接收来自服务器的消息,而另一个线程等待用户输入以便向服务器发送消息。
我是新手,我的代码目前所做的是:两个线程将单独连接到服务器,这使得服务器将单个客户端识别为两个客户端(因为两个线程分别连接到服务器)。我如何解决这个问题,以便接收和发送连接将利用相同的连接?
我已经包含了我的客户端代码的相关部分(连接到服务器是通过函数connectToServer)
/*thread for sending messages to server*/
DWORD WINAPI send_handle_thread(LPVOID threadInfo)
{
/*structure contains all the data this callback works on*/
myThreadArgument* send_argument = (myThreadArgument*)threadInfo;
/*get client connection*/
myTcpSocket my_client(PORTNUM);
string server_ip_address = "";
readServerConfig(server_ip_address);
my_client.connectToServer(server_ip_address, ADDRESS); //this is where the thread connects to server
while (1)
{
/*send messages*/
}
return 1;
}
/*thread for receiving messages from server*/
DWORD WINAPI rec_handle_thread(LPVOID threadInfo)
{
/*structure contains all the data this callback works on*/
myThreadArgument* send_argument = (myThreadArgument*)threadInfo;
/*get client connection*/
myTcpSocket my_client(PORTNUM);
string server_ip_address = "";
readServerConfig(server_ip_address);
my_client.connectToServer(server_ip_address, ADDRESS); //this is where thread connects to server
int rec_bytes = 0;
while (1)
{
/*receive messages*/
}
return 1;
}
int main()
{
/*build a semaphore to synchronise access to std::cout*/
mySemaphore cout_semaphore(string(""),1);
/*initialize the winsock library*/
myTcpSocket::initialize();
/*get local (client) information (assume neither the name nor the address is given)*/
myHostInfo client_info;
string client_name = client_info.getHostName();
string client_ip_address = client_info.getHostIPAddress();
cout << "local host (client) information: " << endl;
cout << " name: " << client_name << endl;
cout << " address: " << client_ip_address << endl << endl;
/*retrieve server's IP name and address*/
string server_ip_address = "";
readServerConfig(server_ip_address);
myHostInfo server_info(server_ip_address, ADDRESS);
string server_name = server_info.getHostName();
cout << "remote host (server) information: " << endl;
cout << " name: " << server_name << endl;
cout << " address: " << server_ip_address << endl;
/*retrieve client's IP name and address*/
myTcpSocket my_client(PORTNUM);
cout << my_client;
/*create thread to send messages to server*/
myThreadArgument* send_argument = new myThreadArgument(&my_client, &cout_semaphore, client_name);
myThread* send_thread = new myThread(send_handle_thread, (void*)send_argument);
send_thread->execute();
/*create thread to receive message from server*/
myThreadArgument* rec_argument = new myThreadArgument(&my_client, &cout_semaphore, client_name);
myThread* rec_thread = new myThread(rec_handle_thread, (void*)rec_argument);
rec_thread->execute();
while (1)
{
Sleep(300);
cout << "main thread";
}
return 1;
}
connectToServer 代码:
void myTcpSocket::connectToServer(string& serverNameOrAddr,hostType hType)
{
/*
when this method is called, a client socket has been built already,
so we have the socketId and portNumber ready.
a myHostInfo instance is created, no matter how the server's name is
given (such as www.yuchen.net) or the server's address is given (such
as 169.56.32.35), we can use this myHostInfo instance to get the
IP address of the server
*/
myHostInfo serverInfo(serverNameOrAddr,hType);
// Store the IP address and socket port number
struct sockaddr_in serverAddress;
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = inet_addr(serverInfo.getHostIPAddress());
serverAddress.sin_port = htons(portNumber);
// Connect to the given address
try
{
if (connect(socketId,(struct sockaddr *)&serverAddress,sizeof(serverAddress)) == -1)
{
#ifdef WINDOWS_7 //XP
int errorCode = 0;
string errorMsg = "error calling connect():n";
detectErrorConnect(&errorCode,errorMsg);
myException socketConnectException(errorCode,errorMsg);
throw socketConnectException;
#endif
#ifdef UNIX
myException unixSocketConnectException(0,"unix: error calling connect()");
throw unixSocketConnectException;
#endif
}
}
catch(myException& excp)
{
excp.response();
exit(1);
}
}
只需在两个位置使用相同的套接字FD。使用时甚至不需要同步
相关文章:
- 最佳做法是从另一个线程访问 qml 中的Q_PROPERTY
- 从子线程访问指针
- 对C++中的队列进行多线程访问
- 对全局变量的多线程访问:我应该使用互斥锁吗?
- cuda:多个线程访问同一个全局变量
- 多个线程访问同一个 cuda 流
- 在为工作线程访问 lambda 中捕获的向量列表中的元素引用时,是否需要互斥锁?
- 从多个线程访问类对象
- 多个线程访问共享资源
- 当并行线程访问同一数据结构的其他成员时,正确的方法可以在Visual Studio上的OpenMP上并行循环
- 从多个线程访问 QTcpSocket
- 从第二个线程访问主线程中的变量
- 在关闭时升级登录中的启动线程访问违规
- 如何使用不同的线程访问Singleton类成员功能
- std::d eque 和多线程访问
- 我可以从不同的线程访问COM对象的接口吗
- 如何从其他线程访问QWidget
- STD ::线程访问从共享库加载的函数
- Android:从其他线程访问OpenGL
- 如果从其他线程访问(读/写)src缓冲区,是否有可能从memcpy获得访问冲突