std :: async를 사용하여 작업에 소켓이 관련된 경우 작업을 병렬로 실행하는 데 문제가 있습니다.표준 C++ TCP 소켓, std :: async 사용할 때 EINTR로 연결이 실패합니다.
내 프로그램은 Linux 용 표준 C++로 작성된 간단한 TCP 소켓 서버입니다. 클라이언트가 연결되면 전용 포트가 열리고 별도의 스레드가 시작되므로 각 클라이언트는 자체 스레드에서 서비스됩니다.
클라이언트 개체는 맵에 포함되어 있습니다.
모든 클라이언트에게 메시지를 브로드 캐스팅하는 기능이 있습니다. 나는 원래 다음과 같이 썼다 :
// ConnectedClient is an object representing a single client
// ConnectedClient::SendMessageToClient opens a socket, connects, writes, reads response and then closes socket
// broadcastMessage is the std::string to go out to all clients
// iterate through the map of clients
map<string, ConnectedClient*>::iterator nextClient;
for (nextClient = mConnectedClients.begin(); nextClient != mConnectedClients.end(); ++nextClient)
{
printf("%s\n", nextClient->second->SendMessageToClient(broadcastMessage).c_str());
}
나는 이것을 테스트했고 3 명의 클라이언트와 동시에 작동한다. 메시지는 세 개의 클라이언트 (한 번에 하나씩)에 도착하고 응답 문자열은이 루프에서 세 번 출력됩니다. 그러나 메시지가 한 번에 하나의 클라이언트에만 전달되기 때문에 속도가 느립니다.
더 효율적으로하기 위해 모든 클라이언트에 대해 SendMessageToClient 함수를 비동기 적으로 호출하기 위해 std :: async를 활용하고 싶습니다. 위의 코드를 다음과 같이 다시 작성했습니다.
vector<future<string>> futures;
// iterate through the map of clients
map<string, ConnectedClient*>::iterator nextClient;
for (nextClient = mConnectedClients.begin(); nextClient != mConnectedClients.end(); ++nextClient)
{
printf("start send\n");
futures.push_back(async(launch::async, &ConnectedClient::SendMessageToClient, nextClient->second, broadcastMessage, wait));
printf("end send\n");
}
vector<future<string>>::iterator nextFuture;
for(nextFuture = futures.begin(); nextFuture != futures.end(); ++nextFuture)
{
printf("start wait\n");
nextFuture->wait();
printf("end wait\n");
printf("%s\n", nextFuture->get().c_str());
}
위의 코드는지도에 클라이언트가 하나 뿐인 경우 예상대로 작동합니다. 당신은 "빨리 보내기"에 이어 "보내기 시작"과 "시작 대기"로 빠르게 따라 가기 시작하고 3 초 후에 (나는 이것을 테스트하기 위해 클라이언트 응답 측에서 3 초 잠을 자는데) 당신은 소켓에서 트레이스를 보게된다. 응답이 들어오는 읽기 기능을 수행하고 "end wait"메시지가 표시됩니다.
문제는지도에 둘 이상의 클라이언트가있는 경우입니다. "4 연결되지 연결된 클라이언트 스레드"
// connected client object has a pipe open back to the client for sending messages
int clientSocketFileDescriptor;
clientSocketFileDescriptor = socket(AF_INET, SOCK_STREAM, 0);
// set the socket timeouts
// this part using setsockopt is omitted for brevity
// host name
struct hostent *server;
server = gethostbyname(mIpAddressOfClient.c_str());
if (server == 0)
{
close(clientSocketFileDescriptor);
return "";
}
//
struct sockaddr_in clientsListeningServerAddress;
memset(&clientsListeningServerAddress, 0, sizeof(struct sockaddr_in));
clientsListeningServerAddress.sin_family = AF_INET;
bcopy((char*)server->h_addr, (char*)&clientsListeningServerAddress.sin_addr.s_addr, server->h_length);
clientsListeningServerAddress.sin_port = htons(mPortNumberClientIsListeningOn);
// The connect function fails !!!
if (connect(clientSocketFileDescriptor, (struct sockaddr *)&clientsListeningServerAddress, sizeof(clientsListeningServerAddress)) < 0)
{
// print out error code
printf("Connected client thread: fail to connect %d \n", errno);
close(clientSocketFileDescriptor);
return response;
}
출력 읽 열리고 소켓에 연결 SendMessageToClient 함수의 부분에서는, 다음 식별 코드 실패.
내가이 오류 코드를 위로 보았다, 그것은 이렇게 설명 :#define EINTR 4 /* Interrupted system call */
나는, 인터넷에 주변 검색 내가 찾은 모든 신호에 의해 중단되고 호출 시스템에 대한 몇 가지 언급했다.
메시지 보내기 기능을 한 번에 하나씩 호출 할 때이 기능이 작동하는 이유를 아는 사람이 있습니까?하지만 비동기를 사용하여 메시지 보내기 기능을 호출하면 실패합니다. 누구든지 여러 클라이언트에게 메시지를 보내야하는 다른 제안이 있습니까?