|
|
 Prize winner in Competition
"Best C++/MFC article of February 2009"
Comments and Discussions
|
|
 |

|
Hi
First of all thank you for such great article and code. It's really useful.
I have to know IP address of closed connection. I mean in OnConnectionDropped or something similar.
I have list of connections from peers, when one of them dropped, I have to know which one is it. How can I do that?
Thanks again!
|
|
|
|

|
TCP only: In your handler, OnConnectionDropped, you can call GetPeerName() to get it
Thanks, I am glad you found the code useful
|
|
|
|

|
Hi, thanks for replying. I really appreciate your help and your willing to help people by answering their question, even 3 years after posting the article.
To be honest, I already tried that and it always returns NULL (nothing), that's why I asked. Have you tried it yourself? Because GetPeerName tries to resolve/find details on an already closed connection.
|
|
|
|

|
yes,i am found like you saied,it's returns NULL
somebody help?
|
|
|
|

|
Sorry I am swamped, I thought I responded you...
In my project, I keep a list/map of client connection (which has the address at the time when the session is established).
I never noticed that it returned NULL but in any case, it seems the best thing to do is to store the address early.
|
|
|
|

|
Hi Ernest Laurentin,
First of all, thanks for your article. It's is very useful for all who are beginners in socket programming. I want to implement the similar functionality in my application, I see the thread count is increasing for each new client connection. Is there anyway to control all the client connections with limited number of threads in sockerserver.exe?
Your answer will be very helpful, iam beginer in the socket programming.
Thanks & Regards,
Chandrashekhar
modified 5 Oct '12 - 6:45.
|
|
|
|

|
This article helped me to integrate FTP-Server-functionality into my project within a few hours! Thank you very much!
|
|
|
|

|
in linux, [root@localhost SocketPort]# ./sockport localhost 1234
Failed to connect to server.
cause: getaddrinfo(pstrHost, pstrService, &aiHints, &aiList) ) return -2.
why ?
i write other application ,and parameter is same ,no problem.
do you testing in linux ?
please look your's makefile ,in linux ,make false ,cause : in linux use thread.h ,you ca n have libs = -l pthread.
|
|
|
|

|
linux :without server example?
|
|
|
|

|
Use SocketPort_linux.zip right?
Also look the makefile:
# you may need to add (-pthread) to build
|
|
|
|

|
yes,i know.
but ,why getaddrinfo(pstrHost, pstrService, &aiHints, &aiList) ) return -2?
|
|
|
|

|
if i modify : if ( SOCKET_ERROR != getaddrinfo("127.0.0.1", pstrService, &aiHints, &aiList) && ( aiList != 0 )),this no problem,but back connect failed.
|
|
|
|

|
it is a great job. and thanks for your sharing ! thanks.
can you just help me with the follow problem.
when this project recevice 5k bytes unicode data(tBufferSize=1024),it calls OnDataReceived(...) five times .I can understand this. but the problem is that。in the third time of OnDataReceived(....) the unicode data has some messy codes. I just don,t understand what happen for this. I need your addvices. thanks a lot.
ps:the messy codes like this:192.168.100.31 : 1981>(ぶ薜盒鲁俏宥泳潭馐訞 ,192.168.100.31 : 1981>(硬馐园∷藹
modified 20 Apr '12 - 1:10.
|
|
|
|
|

|
Thanks for your timely reply . In order to make sure the message is fully received . I give the passing message an EOM --"END". And I test again. I set template of both server and client .But when I send more than 1 k (1024 bytes) data to server . and the server receives the all the data.(because server already receives the EOM --"END") the data still contains messy data .So,I think there must be someting wrong when the server is receiving the data or there must be something wrong where the client sending the data .(here ,you must know this first :the data contains unicode data and the data size is bigger than the tBufferSize of server's and client's.)
The follow code is the test code of the server receiving data (this code basees on your demo code)
ASSERT( pSH == m_SocketServer );
(pSH);
CString strAddr, strText;
USES_CONVERSION;
LPTSTR pszText = strText.GetBuffer(dwCount+1);
::StringCchCopyN(pszText, dwCount+1, A2CT(reinterpret_cast(pbData)), dwCount);
strText.ReleaseBuffer();
GetAddress( addr, strAddr );
// AppendText( _T("%s>(%s)\r\n"), strAddr, strText);
// the folow code is add by me
m_data+=strText;
if(strText.Mid(strText.GetLength()-3)=="END")
{
AppendText( _T("%s>(%s)\r\n"), strAddr, m_data);
MessageBox(m_data);
m_data="";
}
and the test result is this. It's a picture but i don't know what to upload. Thanks for your reply again !
|
|
|
|

|
I really like the work you have done. That's what I'm looking for. Thank you very much!
|
|
|
|
|

|
My Remote Desktop Program could really benefit from something like this. I created a multi-threaded socket implementation but I've never been happy with it or its stability. Perhaps you could look over my code on Code Project and we could collaborate in a way to bring your work and mine together.
Remote Control PCs
|
|
|
|

|
Hi Randy,
A remote desktop - sounds cool project *but* I am like busy like crazy. Busy is good though. I will keep that in mind since I had wanted to develop something like that.
|
|
|
|

|
How can i send message to a certain client? there is a list about client in source code,but i can't find function to distinction the clients, like ip,or host name.
I'm looking forward for your help.
thanks.
I just mean use the tcp . not the UDP ... thanks..
|
|
|
|

|
SockAddrIn tempaddr;
const SocketList& sl = m_Server.GetSocketList();
for(SocketList::const_iterator citer = sl.begin(); citer != sl.end(); ++citer)
#endif
{
CSocketHandle sockHandle;
sockHandle.Attach((*citer));
sockHandle.GetPeerName(tempaddr);
if(addrIn.IsEqual(tempaddr))
sockHandle.Write(lpbData, data.GetLength(), NULL);
sockHandle.Detach();
}
this is the solution of my own question...thanks...
|
|
|
|

|
that's great code,it's for me need thks
|
|
|
|

|
Thanks, it is what I need.
|
|
|
|

|
hi,
First, it's a must to thank the author for this excellent article.
I compiled the sample on WinXP using VS2005, the compiler complains:
sockethandle.cpp(1051) : error C2065: 'AI_ADDRCONFIG' : undeclared identifier
It seems that AI_ADDRCONFIG is only available on Windows SDK for vista or later, what is the appropriate way to fix this error in my case? Thanks in advance.
See AI_ADDRCONFIG explanation on MSDN :
http://msdn.microsoft.com/en-us/library/windows/desktop/ms738520(v=vs.85).aspx[^]
|
|
|
|

|
Download the latest SDK...
...or you can include 'Ws2tcpip.h' in your stdafx.h
|
|
|
|

|
I was looking for sample UDP/TCP code in C++ and found your well-written article and source. Many thanks for making the job easier.
|
|
|
|

|
I want to use your code in a project of mine. The data is send from the server (UDP), on random, now if I close the client, during the data is send, I get a crash. Can you give me advice on how to properly close the connection between the client and the server...?
P.S. I think your article is one of the best in this site.
|
|
|
|

|
I am just should be called a senior coder. Without much experience with socket programming and I am looking for some projects or libraries or samples to learn it. This assay has given me much beneficial knowledge and I am appriciated to you.
|
|
|
|
|

|
Hi Ernest,
I find the socket cannot transfer data encode with BlowFish .
you can find more details here www.schneier.com/blowfish.html[^]
That's to say it cannot transfer Unicode data.
Thank you.
|
|
|
|

|
There is no limitation about sending raw/Unicode data. Verify that you are setting the length of data correctly.
|
|
|
|

|
Ernest, since you been working with this stuff, I have a question. The direction has been of in recent years (within the Windows and multi-core world) to move towards process centric frameworks as scaling thread-centric frameworks can have a high overhead in particular when a "autononous" thread can have a wide range of dependencies (i.e. other threads started). The current example are web browsers with Chrome moving towards a process-centric framework where each web site is its own CHROME.EXE proccess and IE 9.0 following this lead. When a thread was spawn per web site under the management of one process, a breakdown meant all current web site threads (i.e. tabs) were shutdown. The same is true when DLL for different services faults and that stops all DLL services running under one process.
So do you think when the start up and tear down overhead of an connection instance is minimal, can QueueUserWorkItem() be used to start an instance as a process instead of threads? (i.e passing the hot socket handle to the process)
|
|
|
|

|
Interesting question but I think for Web browser to move away from thread-centric is more security and stability. For example, a plug-in would not be able to do as much damage.
When you look at the source code of Chrome for example, there are a lot more going on...shared memory and pipes are used. QueueUserWorkItem is a nice function but you can do a whole lot better with the new thread pool functions (Vista, Windows 2008(R2)). QueueUserWorkItem can be a little tricky, especially under 2003. It doesn't always start your task immediately. The thread pool is managed by the OS. You will get better control with the new API.
Of course, you can start a process instead...but as far Chrome, IE, etc. it's more a security and stability issue.
|
|
|
|

|
yes, both security and stability, more stability because even without security issues, the nature of the javascript coding (V8) had alot of multi-threading contention and bottlenecks.
|
|
|
|

|
Hi, back in 2009, when this was first posted, I explored it to see if it can be used to revamp our 15 years TCP server that was never a problem until Microsoft began to change the OS internal thread and socket management begin the Vista/2008/Windows 7 and thru service packs also it also altered how XP, 2003 behave all in the name of MULTI-CORE computers. Trust me when I say thru "Divide and Conquer" I was able to reduce and repeat the problem with a simple socket client/server, enough to get MSDN MVP to confirm the problem.
In short, a traditional client/server application using self-deleting client socket connection handler class was intermittent now causing a MEMORY LEAK under MULTI-CORE computers, NOT SINGLE or true MULTI-CPU computers. This was confirmed MSDN MVP back in 2009 with the simple example provide to problem how Microsoft added wrappers to the socket layer and thread management created memory leaks which never existed before. Indirectly, MSDN articles existed with observed similaar behavior (though not indicating a MULTI-CORE relationshop) where a IOCP design approach was suggested.
Using an IOCP does indeed solve the problem. It also showed it offers a high scalability.
The problem for use was production code that was very complex with many IPC integrated ideas and we didn't have a HIGH SCALE need. At most 25 connections per sec was all we needed and that always worked, one thread per conneciton as it came in. We didn't need to serve 10000000000 connections!
So I began to see if there was a simple "pool" class where I can pass it our socket connection handler class to solve this memory leak problem under MULTI-CORE computers.
In short, I need to find a "thread pool" class where I can start it up globally up:
CThreadPool <CMySocketHandler> Pool();
and in the listening server thread, when a connection comes in, I can just pass the handle to the pool:
while (1) {
sockaddr_in src;
int x = sizeof(src);
SOCKET t = accept(hListenSocket, (sockaddr *)&src, &x);
if (t != INVALID_SOCKET) {
pool.NewConnect(t);
}
}
Can I do this with the classes in this project?
Thanks in advance
|
|
|
|

|
The ThreadPool class provides only a couple of static functions where you probably could do that.
It's not very hard to change this class to use IOCP. The only reason that I was written without IOCP support is because of Windows CE and Unix. It supports asynchronous/non-blocking sockets if you prefer.
|
|
|
|

|
Hmmm, I would swear that that QueueUserWorkItem() used I/O completion ports internally. But probably not for sockets.
The basic problem is that even if your simple client/server application with a classic listening server starting a thread per connection with tha self-deleting class handle never had a memory leak problem, now with the lower level OS changes to add new memory management (Low Fragmenation Heap), IOCP, Winsock2 and changing of handles, you have memory leaks. In other words, microsoft force the design change to use worker/handle pools even if you don't need a high scaled system. After almost a year of reaching this, putting it aside and coming back and doing more researching, Mark Russinovich, was able to expain the final piece of the problem.
- Application release handle.
- CSRSS process takes ownership to return it the OS "POOL" of handles.
- Using some magic formula it releases it in X, Y, Z times.
- With the intro of LFH (Low Fragramentation Heap) which as I got from Mark is a "security" solution to lower the predictability of where heap memory is allocated, its possible due to the CSRSS held handle, the memory fragramention increases in your application causing VM problems.
What i am seeing is that this only occurs with Multi-core computers. Confirmed by others.
So basically MS forced the issue by trying to be "smart" to manage resources pools even for those applicaiton that did not create its own pools. I don't neeed 50/100/1000 connections clients. At most, 5-10 threads and thats if they all come in at the same time. So I am going to see if I can use a self-deleting thread (releasing its own handle) with your ThreadPool classs will resolve the memory leaks,.
|
|
|
|

|
BTW, here is the link the self-deleting class posted at MSDN and the discussion thread where towaards the end, you see a confirmation.
http://social.msdn.microsoft.com/Forums/en/vcgeneral/thread/93baaffb-f0ac-4fd5-baf2-0482b217d2b6
The self-deleting thread is instantiated in my listening server:
new CMyAutoThread(new_connection_socket_handle);
The derived class of CAutoThread, passing new connection socket handle , is what I want to see if how to use in ThreadPool template class.
|
|
|
|

|
I reviewed your link. This is pretty standard way to manage a thread.
I prefer the pool approach.
|
|
|
|

|
Sorry, disregard last partial message (now deleted), this dumb codeproject editor doesn't like when Javascript is disabled and clinking one of the buttons (i.e. link) caused it to unfinished messsage to be posted.
It seems you have no choice (using pools) now under Windows's Low Fragramentation Heap (LFH) manager. See this links
http://msdn.microsoft.com/en-us/library/aa366750(v=vs.85).aspx
Applications that benefit most from the LFH are multi-threaded applications that allocate memory frequently and use a variety of allocation sizes under 16 KB. However, not all applications benefit from the LFH. To assess the effects of enabling the LFH in your application, use performance profiling data.
Once a thread creates allocates more than 16K, fragmentation grows and worst when non-pool threads are used. I'm playing with QueueUserWorkItem() now to reduce the problem without drasticallly changing my code.
|
|
|
|

|
Hmmm...Then, allocate memory less often.
Use memory pool or circular buffer.
Good luck, great discussion!
|
|
|
|

|
We have no control of whats allocated with 3rd party developers. We do so specific things like ODBC and a global heap for a pcode RTL. We did have control .... until Mickeysoft tried to be smarter and do us a favor, but made things worst unfortunately. In other words, not everything is .NET managed. :(
|
|
|
|

|
Hi,
Thank you for your great job! it works very well in my project.there are 2 questions for me:
1. How can i refuse some certain ip when client try to connect to server. it seems that server allow all the client to connect.
2. How can i send message to a certain client? there is a list about client in source code,but i can't find function to distinction the clients, like ip,or host name.
I'm looking forward for your help.
thanks.
bzcode
2011-6-10
|
|
|
|
|

|
Great article and classes. Thanks for sharing!
|
|
|
|

|
Thank you very much for your article. It has helped me a lot in developing my application
I had a serious problem with the Terminate call though. If I specified a timeout the main thread always terminated through the TerminateThread call. The result of this is that some CSocketServer resources were not released correctly and the socket was left hunging (I watched them pile up at TcpView). When I used INFINITE the application just hunged.
It took me a while until I realized that there is a racing condition in CSocketHandle::IsOpen function
when I replaced
return ( INVALID_SOCKET != m_hSocket );
with
return ( INVALID_SOCKET != InterlockedCompareExchange( (LONG*)&m_hSocket, INVALID_SOCKET, INVALID_SOCKET) );
everything worked correctly.
Thanks again
|
|
|
|

|
Strange...Did you change thread priority somewhere in your code?
Also, are you seeing this with the Asynchronous version?
Thanks for your feedback!
|
|
|
|

|
It looks strange to me too. After this change sockets are not left hunging in tcpview's screen and the port can be used agian in next runs. But the symptom has not gone away. The main thread never leaves the while loop. I have added a debug printf acter the waitforconnection cal
while( _socket.IsOpen() )
{
SOCKET newSocket = CSocketHandle::WaitForConnection(sock);
odprintfA("ASocketServerImpl::Run accept returns");
if (!_socket.IsOpen())
break;
odprintfA above gets executed only after each succesfull connection is made by a client. Never by the Terminate function call. That means that main thread is always destroyed by TerminateThread call. The change I described before affected only the threadpool version not the asynchronous one. Both version show the same behavior though. Main thread never exists normally.
I am thinking of two things that I should check out
1. The possibility that the thread creating the class and hence the main thread must be a UI thread (message queue)
2. Since it looks like that the code never exits the accept call I am going to modify Terminate function so as it sets a boolean flag (exiting) and then create a connection to the socket just to force it to exit the blocking accept call. I guess this will force the main thread to exit gracefully
What puzzles me even more is that I have never managed to replicate this behaviour in you socketserver demo. Both applications demo & mine are build against the same SDK (6.1) and their only difference is that the demo is an MFC app and mine an ATL windows service.
regards,
George
|
|
|
|

|
2nd method above worked. Now the thread terminates gracefully calling OnThreadExit() as it should.
I have to get rid of all debug code and write the bogus connection in a better way and then I am done.
regards,
George
|
|
|
|

|
You may simply have to call CloseAllConnections() in your server.
|
|
|
|
 |
|
|
General News Suggestion Question Bug Answer Joke Rant Admin
Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.
|
Complete Client/Server Socket Communication class with threadpool implementation. Easy to use and integrate into C++ application. Linux/UNIX port available.
| Type | Article |
| Licence | Apache |
| First Posted | 12 Feb 2009 |
| Views | 202,852 |
| Downloads | 16,487 |
| Bookmarked | 339 times |
|
|