c++ - 如何为多线程客户端访问多个线程上的同一个套接字

标签 c++ multithreading sockets client client-server

我有一个多线程客户端,设置它是为了在一个线程上从服务器接收消息,而另一个线程等待用户输入以便向服务器发送消息。

我是新手,我的代码目前所做的是:两个线程将单独连接到服务器,这使得服务器将单个客户端识别为两个客户端(因为两个线程分别连接到服务器)。我该如何解决这个问题,以便接收和发送连接使用相同的连接?

我已经包含了我的客户端代码的相关部分(通过函数 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。使用它时您甚至不必同步。

关于c++ - 如何为多线程客户端访问多个线程上的同一个套接字,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/15331704/

相关文章:

javascript - jQuery Web Socket 未连接且未发送

c++ - 使用套接字在 C++ 中进行客户端到服务器身份验证

c++ - 是否有减少完整 Doxygen 覆盖所需的冗余注释量的技巧?

c++ - 不分离模板类的函数声明和定义是一个好习惯吗?

c# - Parallel.ForEach错误

java - 了解具有线程和同步的共享对象

c++ - 无法将数组中的负值转换为正值?

c++ - 模板类特化与函数重载

c# - 基于需要在执行时间内接收更多项目的列表执行 Parallel.ForEach

c - 为什么 select() 对收到的消息没有反应?