简体   繁体   English

如何为多线程客户端访问多个线程上的相同套接字

[英]How to access same socket on multiple threads for multi-threaded client

I have a multi-threaded client that's set up in order to receive messages on one thread from the server, while the other thread waits for user input in order to send a message to the server. 我有一个多线程客户端,它的设置是为了从服务器的一个线程上接收消息,而另一个线程等待用户输入以便将消息发送到服务器。

I am new to this, and what my code currently does is: both threads would individually connect to server, which made the server recognise the single client as two clients (since both threads connected to server individually). 我对此并不陌生,我的代码当前正在执行的工作是:两个线程将分别连接到服务器,这使得服务器将单个客户端识别为两个客户端(因为两个线程都分别连接到服务器)。 How do I fix this so that the receive and send connections would utilise the same connection? 如何解决此问题,以便接收和发送连接将利用相同的连接?

I have included the relevant portion of my client code (connecting to server is through the function connectToServer) 我已经包含了客户端代码的相关部分(通过功能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 code: 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);
}
}

Just use the same socket FD in both places. 只需在两个地方使用相同的插座FD。 You don't even have to synchronize when using it. 使用时甚至不需要同步。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM