簡體   English   中英

如何為多線程客戶端訪問多個線程上的相同套接字

[英]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。 使用時甚至不需要同步。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM