patterncppMinor
Multithreaded Socket code to connect to 100 different machines
Viewed 0 times
connectdifferent100machinescodesocketmultithreaded
Problem
This is my socket.cpp
This is mysocket.h
```
//----------------------------------------------------------------------
#pragma hdrstop
#include "MySocketClient.h"
MySocketClient::MySocketClient() throw(SocketException){
WSAData data;
InitializeCriticalSection(§_);
if(WSAStartup(MAKEWORD(2,2),&data)!=0){
throw SocketException("Cant load WinSock library");
}
connected_=false;
}
//-----------------------------------------------------------------------------
MySocketClient::~MySocketClient(){
WSACleanup();
}
//-----------------------------------------------------------------------------
void MySocketClient::receive(void){
char recBuf[1024];
while(1){
EnterCriticalSection(§_);
memset(recBuf,0,1024);
int recLen=recv(sock_,recBuf,1024,0);
if(recLen==0){
onDisconnect(sock_);
connected_=false;
break;
}else if(recLenh_addr_list[0];
if(connect(sock_,(sockaddr*)&addr_,sizeof(sockaddr))==SOCKET_ERROR){
throw SocketException("Connect Error");
}
DWORD dwThreadId;
threadHandle_=CreateThread(NULL,0,startReceive,this,0,&dwThreadId);
if(threadHandle_==NULL){
connected_=false;
shutdown(sock_,SD_BOTH);
closesocket(sock_);
throw SocketException("Receive thread create error");
}
connected_=true;
onConnect(sock_);
}
//------------------------------------------------------------------------------
void MySocketClient::Disconnect(void){
TerminateThread(threadHandle_,0);
shutdown(sock_,SD_BOTH);
closesocket(sock_);
}
//Virtual functions
void MySocketClient::onReceive(SOCKET sock,char *recBuf,int recLen) throw(SocketException){
}
void MySocketClient::onDisconnect(SOCKET sock){
}
void MySocketClient::onConnectionError(SOCKET sock){
}
void MySocketClient::onSendData(char *sendBuf,int sendLen){
}
void MySocketClient::onConnect(SOCKET sock){
}
#pragma package(smart_init)This is mysocket.h
```
//----------------------------------------------------------------------
Solution
It could be that at 100 connections you won't notice, but you should be aware that the 1-thread-per-connection model does not scale well and is not in line with the current state of the art. See what is written about the c10k problem.
With a thread-per-connection approach you will have high memory overhead from each thread's stack, and you will spend a lot of time context switching.
What scalable network code does these days is:
-
On Unix: Use
-
On Windows: Issue your I/O with "overlapped" I/O, and use I/O completion ports or APC to be notified when the I/O is finished.
In both of these models the ultimate goal is to not spend time waiting for synchronous I/O, such as a blocking read or write to the socket. This allows you to process multiple requests without needing multiple threads.
With a thread-per-connection approach you will have high memory overhead from each thread's stack, and you will spend a lot of time context switching.
What scalable network code does these days is:
-
On Unix: Use
epoll (Linux), kqueue (*BSD) or equivalents with non-blocking sockets. The model here is that you ask the kernel to block until some file descriptor is ready for I/O. It informs you which fd is ready and you can issue the non-blocking read or write.-
On Windows: Issue your I/O with "overlapped" I/O, and use I/O completion ports or APC to be notified when the I/O is finished.
In both of these models the ultimate goal is to not spend time waiting for synchronous I/O, such as a blocking read or write to the socket. This allows you to process multiple requests without needing multiple threads.
Context
StackExchange Code Review Q#15901, answer score: 4
Revisions (0)
No revisions yet.