More socket server code updates

| 49 Comments | 1 TrackBack

The latest release of the free version of my asynchronous, windows, IOCP based, socket server framework can now be obtained from here at ServerFramework.com.

I've updated the code for two more of the socket server articles. More merging, project file updating, and testing...

[NOTE: This code leaks when adjusted to build with Visual Studio 2005. This seems to be due to a bug in VS2005's STL. See here for a workaround. I expect to post a fix for this once I've found time to convert the code to build with the new compiler and then tracked down the leak. If anyone has already done this then a comment telling me what's wrong would be appreciated.]

For the change list see here.

The code for the Business logic processing in a socket server article is here.

And the code for the Handling multiple pending socket read and write operations article is here.

I'm not sure if I'll get around to updating the AcceptEx article and the UDP version of the code. Both of those code paths really need to be merged into the main set of code in a less cut and pastey style. Right now they're a nightmare to maintain - just as you'd expect from cut and paste reuse :(

1 TrackBack

TITLE: re: Yes it's been while...but also meandering onto Winsock2 URL: http://blogs.wdevs.com/philharding/archive/2005/10/25/10956.aspx IP: 217.160.175.238 BLOG NAME: More Soma Please... DATE: 10/25/2005 10:51:44 AM Read More

49 Comments

good code

Hi,

nice work ,
but...
i have VS6.0 with SP5. and SDK installed but i could not compile your code...
also
i could not compile the new versions...

best regards.
erdi

Erdi,

Try harder ;) or at least give me a clue as to the error messages that you get...

SocketAddress.cpp complains about SOCKET not being defined like 109 time ;)

Did this:
#include "WinsockWrapper.h"
//#include

in SocketAddress.h and it's fixed, right?

Oops. In my previous post instead of
//#include
read
//#include <winsock2.h>

Max,

Right. I dont compile without the latest platform SDK and it doesnt happen if you have it. Thanks for the heads up. I'll fix the code.

Len

Hi Len,

Great job on your socket server framework! I want to use it in my existing MFC server application. Before I am going to use it I have few questions on how to extend your framework to meet some of the requirements of my server application. My server application wants to output any socket data messages, exceptions that would occur during the socket transmission into a MFC-based view. What is the best approach to ensure that the data output is thread-safe? One method is to have the business logic worker thread to save the output data into shared memory and then post a message back to the view and then have it to fetch and display the data. I am worry about the performance with this method because I have to protect the writing and the reading of the shared memory. Is there any other methods? I am using the business-logic thread pool server framework. Any examples will be very appreciated.

Thanks in advance,

Dennis

Dennis

We never give our server's a UI so we never have the problem. What we tend to do if and when we need to provide a UI for a server is have the server listen on a port for UI connections and then have it broadcast UI messages to all connected users... This seems to solve all of the nastiness and has the added advantage of allowing the UI to be run anywhere and for multiple UI's to run if required...

If you really must have the UI as part of the server then I'd suggest posting thread messages to your UI thread and using the CBuffer to handle memory allocation etc (allocate a buffer in the socket server thread, post the buffer as a thread mesage to the UI thread and release the buffer in the UI thread when you're done with it...)

Hi Len,

Thanks for quick response. In my case I only have one connected user. Your first suggestion suggests that I need to maintain two servers? One to listen on the UI client? And another one to listen on the normal clients? Given your server framework, how can I transfer socket data from one server to another server inside the business logic worker thread? Do I need to pass another instance of Socket Server in each Socket so that I can access it in the business logic thread? A example would be helpful.

As for your second suggestion, I think it is easier to implement but not as flexible as your first approach. This is how I would implement using standard windows APIs.

Inside the business logic thread, where hParentHandle is a HWND handle of my MFC-view and hFunctionHandle is the registed window message handle for the mapping function, DisplayStatus():
...
TCHAR* sTestString = new TCHAR[20];
PostMessage(hParentHandle, hFunctionHandle, (WPARAM)sTestString, (LPARAM) GetCurrentThreadId());
...

In the MFC view:
LRESULT CView1::DisplayStatus(WPARAM wParam, LPARAM lParam)
{
...
TCHAR* s = (TCHAR *)wParam;
// display the data
...
delete[] s;
return 0;
}

Please tell me how can I use your CIOBuffer APIs to do the same thing. Is it thread-safe?

Thanks in advance,

Dennis

Dennis

I dont have an example to hand. What I've done in the past is have the UI server maintain a list of connected users and provide a thread safe interface for writing to all the users. You then pass this interface to your thread pool's worker threads and they can then send UI information to the UI clients...

LRESULT CView1::DisplayStatus(WPARAM wParam, LPARAM lParam)
{
...
CBuffer *pData = (CBuffer *)wParam;
// display the data

DumpData(pBuffer->GetBuffer(), pBuffer->GetUsed());
...
pData->Release();
return 0;
}

the advantage of using CBuffer's is that the allocator can be tuned to maintain a number of them in memory so that you're not allocating and deleting memory continually...

Thanks for your answer

Hi Len,

I want to implement some sort of timer feature in your framework to handle the case when I don't get a response back as a result of read, write, or connect. I am thinking to put a timestamp per socket and update the time when a connection, read, and write is established. And then to have a thread constantly looping around a list of opened sockets and determine which one is timeout. I believe I need to put protections on data read and write, which may slow down performance.

Nevertheless, could you give some code segments or psudo-codes on how to implement that with your framework APIs?

Thanks in advance,

Dennis

Dennis,

I wouldn't do it that way ;)

I spent some time thinking about this for a project and ended up with a timer system that was outside of the socket code. This seemed more flexible as we potentially wanted more than one timeout type per connected user...

We ended up with a class called CCallbackTimer. Which is included in the zip file above, in the Win32Tools directory. The class implements a timer queue. It allows you to set timers and keeps the timers that have been set in a list, it has a thread that runs in the background to manage the list and call you back when the timers time out. The thread goes to sleep for the shortest timeout that is currently set and then wakes up and walks the list of timers and signals each that has gone off, it then goes back to sleep for the appropriate amount of time so that it will wake when the next timer is due.

This works well and scales nicely and could be used to implement what you need. Unfortunately I dont have any simple sample code that shows you how it works or is used.

Hi Len,

I have looked at the CallbackTimer class. It seems like what I need. This is my understanding of the usage of the class. Please correct me if I am wrong.

In the socketmain.cpp

CCallbackTimer m_CallbackTimer;
CCallbacktimer::Handle::Callback m_MyCallback;
CCallbacktimer::Handle m_Handle(MyCallback);

Pass m_CallbackTimer and m_Handle to the CSocketServer class at the constructor

At the end of the function call initiateshutdown

In the socketserver.cpp

For example in the OnConnectionEstablished function:

Call m_CallbackTimer.SetTimer(m_Handle, 10000);

If time does not expired and already receive some data, then in the ReadComplete function, add

m_CallbackTimer.CancelTimer(m_Handle, 10000);

I need to override the ontimer function in the Callback class as follows:

void Callback::OnTimer(Handle &hnd, DWORD userData)
{
// Go to a function in the socketserver class
m_SocketServer.OnTimer();
}


I have two questions:

1) Your logic of HandleTimeouts remove the node object once it is expired. If I want to reset the timer again, I have to call SetTimer again?

2) When the time expired, I want to close the socket that is timeout. How do I search for the right socket handle (assuming the system is now maintaining several socket connections)?

Dennis

Dennis

1) Yes, to set the timer again you call SetTimer again...

2) I expect you want a handle (timer) per socket. Derive from the handle, have the derived handle store a pointer to your socket, store the derived handle as userdata in the socket on connection and remove/delete on socket release.

Thank you for your answer.

You have been a great help so far. I have another question. I read in the post from other people that they are doing AddRef on the OnConnectionEstablished and then Release on the OnConnectionClosed, OnClientConnectionClose, and OnConnectError. What is the intention for that? What is the default behavior in the framework?

Thanks in advance,

Dennis

You dont need to call AddRef() on the socket unless you need to keep the socket open when you dont have any reads pending or writes pending.

In most servers, you would call read in on connection established and then call read again each time a read completes. This will maintain the socket's reference count at > 0 and keep the connection open. When the client closes the connection, your read will return due to the client close and you wont be able to queue any more reads, so once your writes complete the socket will have its ref go to 0 and the connection will close...

Sometimes you may need to continue doing stuff on the connection after the client has called shutdown(SD_SEND) (and caused you to get a client close and be unable to read again) in these situations you probably have some well defined situation that signals the end of the useful life of the socket so you would call addref in OnConnectionEstablished() and release at your well defined point...

If you dont issue a read in OnConnectionEstablished and you dont call AddRef() then the socket will close after OnConnectionEstablished returns and any writes that you have issued have completed.

What happen when I issue a read inside OnConnectionEstablished and then did not get any response back. Would the connection still alive?

When you issue a read or a write the reference count on the socket and the buffer involved are incremented. When the read/write completes the appropriate completion routine is called and then the reference counts are decremented. So, what normally happens, is that you issue a read when connection is established and you issue a new read each time a read completes and this keeps the socket's reference count at >0

Just dont mess with the ref counts and copy how the demo servers work and it will all just work.

Ok. There is something in the code of "Large packet echo server" I'm not getting.
In your latest version from june class CThreadPoolWorkerThread has
OnConnectionClosed declared.
But it's never implemented. And in the threadpool.h value ConnectionClosed is gone from here:
enum DispatchEvents
{
ConnectionEstablished,
ConnectionClosing,
ReadCompleted
};
But! In that CThreadPoolWorkerThread::OnConnectionClosed
there used to be pretty usefull I seems code:
void CThreadPoolWorkerThread::OnConnectionClosed(Socket *pSocket)
{
// release per connection data
CPerConnectionData *pData = reinterpret_cast(pSocket->GetUserPtr());
pSocket->SetUserData(0);
delete pData;
}
Where did that go? Thanks.

It's a bug; I removed too much code during the cleanup. See comment here on CodeProject:

http://www.codeproject.com/internet/ReusableSocketServer4.asp#xx744903xx

The socket server code is missing a handler for OnSocketReleased(), it should look like this:

void CSocketServer::OnSocketReleased(
CAsyncSocket *pSocket)
{
Output(_T("OnSocketReleased"));

CPerConnectionData *pPerConnectionData = GetPerConnectionData(pSocket);

SetPerConnectionData(pSocket, 0);

delete pPerConnectionData;

m_pool.OnSocketReleased(pSocket);
}

"CAsyncSocket"? You mean just "Socket", right?
and also that
CThreadPoolWorkerThread::OnConnectionClosed
has to go away than from the header, right?

Max

Yes, CAsyncSocket == Socket in the publically available source. And yes, delete the OnConnectionClosed() in the worker thread.

JM

We could put something together for you, for a fee, or you could use our freely available echo server console app as a starting point. Contact me via email if you're interested in a quote.

hi dear len
ihave used the high performance tcp-ip socket server com codes but in line:
"Set server=CreateSocketServer(CLng(Text1.Text))"
an error accured and said :
"activex component can't create objet"
please tell me what can i do.
thank u
yasmin

Sounds like the you need to register the component...

Len,

I am currently using your business logic thread-pooled socket server in a MFC application. I have a simple question: When I am done with one socket connection, what is the correct way of closing it down? I am not shutting down the whole socket. I just want to release this connection and the current Socket pointer and my custom defined data. I am aware that when another connection comes, another socket pointer and my custom data will be defined.

Len,

I have defined the custom data inside the Per Connection class and the data will be release at the OnSocketRelease function. When I perform my last read or write, I would like to close this connection and its underlying data storage such as socket pointer, Per Connection data. I have looked at the source for Close and AbortiveClose functions, they are closing the socket connection, but not the data storage associated with that connection.

What I would like to see is that when I choose to end a connection, I would like to call the SocketRelease(pSocket) function. Is this the right way to close a normal connection? If I just call the close function, at what point the per connection data will be removed?

Dennis

Dennis

The socket structure is reference counted. If you dont explicitly take a reference within the server by calling AddRef() then the socket will be cleaned up when the last pending operation completes.

Usually it works as follows, in on connection established you issue a read request which increments the reference count. When the read completes you process the data and issue another read before returning, this keeps the reference count above 0 because you have a read pending (you can pretty much ignore the effect that issuing writes has on the reference count).

The easiest way to end a connection is to not issue another read from within the read completion handler. Any writes will complete and then the socket will close and OnSocketReleased will be called to allow you to clean up your per socket data (if any). Of course it's not always possible to do things this way... If you find that you need to shut down the connection after you've issued a read then the best way to do it is to call Shutdown to shut down the send side of the connection. This will cause the client's read to return 0 and enable the client to begin a shutdown procedure if appropriate (it will call shutdown, close the socket and eventually your pending reads will complete and you wont be able to issue more because the client side is shutdown...

If you are taking a reference on the socket within the server (which may be required for some kinds of servers but can usually be avoided) then you need to make sure that you release it at the correct time...

Len,

Thanks for your prompt response. I now understand the normal way to release a connection. How about if some unexpected things happened in my server (such as the client closes the connection prematurely, the user in the my server has requested a close, or something error during the socket transmission), how can I do a graceful shutdown by making sure all my connection data get deleted.

I browse the source code to see the WaitForShutdownToComplete function and it had answered the case when a user in the server GUI requested a shutdown. How about other cases when the client requests a close on that connection (either after a read or a write) or an error happened during socket transmission?

What should I put in the OnConnectionClosing function to make sure the connection data will be deleted?

If an error happened during the socket transmission (such as the user unplugged the network connection or other unexpected things), I would like to shut down my server because if such error happens, it probably won't work for all the connections. If that is the case, what should I put in the OnConnectionError or OnConnectionReset(???) functions?

Thanks in advance,

Dennis

Len,

I think my confusion is that when an unexpected things happened (Client Closed the connection, error during socket transmission), the OnConnectionReset, OnConnectionClosing, OnConnectionClosed, and OnConnectionError function handler will be called depending on the type of error, will the reference count be automatically decreased and eventually calling the SocketRelease function (in the threadpool.cpp) and release my custom data or I have to call it explicitly inside these functions?

Dennis

If the client closes the connection, or the connection is aborted then any pending reads will complete and you're back in the same situation that you were in with the normal shutdown scenario.

The WaitForShutdownToComplete() function is purely for when the server as a whole is shutting down, not when individual connections terminate.

You dont have to put anything in OnConnectionClosing(). The default implementation works just fine.

If you want to shut the server down for some reason then, assuming you're using the 'event based' main() you simply set the shutdown event and the server will shut down... We've never written a server like that though...

Yes when the errors occur the ref counting is handled automatically for you, you dont need to do anything special and the connection will eventually close...

Hi Len,

I was using your CallbackTimer class to handle timeouts during socket communication and I was having a memory leak everytime the OnTimer function is called. I debugged through my source code and found the leak is due to the ref counter for the Node object. The ref counter for the Node has the value of three but it is only decremented two times.

Please see the followings:

// Allocate callback object and then store the current socket pointer for timeout function
CMyCallback* pMyCallback = new CMyCallback(pSocket, m_pool);
// Allocate the handle
JetByteTools::Win32::CCallbackTimer::Handle* pHandle = new JetByteTools::Win32::CCallbackTimer::Handle(*pMyCallback);
// Now store the handle and callback object in the Per Connection Data
// These objects will be deleted on the OnSocketReleased function
pData->SetCallback(pMyCallback);
pData->SetHandle(pHandle);

// Please note that ref counter for Node object is now set to one.

// Now call the timeout
pData->SetTimer(*pHandle, pData->GetTimeout()*1000);
// Please note that ref counter for Node object is now set to two because ref counter is incremented inside the SetTimer function

// When the timer expires and jumps to the OnTimer function, the ref counter is now set at three. When the OnTimer is finished, the ref counter is dropped to two.

// When the connection closes, I delete my Handle inside the OnSocketRelease function and that decrement the ref counter for the node object to one, therefore the object does not get cleared.

// I try to call CancelTimer inside the OnTimer function but it fails because the RemoveFromList function is already called before the OnTimer function is called, and therefore preventing the ref counter for the node object to be decremented.


Could you give me some ideas on how to work around this leak?

Thanks,

Dennis

Dennis,

I think you must be doing something strange... I've just run the test harness for the callback timer and what happens is as follows:

Create a handle - ref count of the node is 1.

Call set timer, ref count of the node goes to 2.

OnTimer, before the call to the callback the ref count is incremented to 3 as the node is wrapped in a handle, after the callback it drops to 2 as that handle is destroyed, after OnTimer completes it drops to 1 when the release corresponding to the addref in SetTimer is called...

Delete the handle and the reference count goes to 0 and the node is deleted.

If you call SetTimer within your OnTimer handler then the ref count will rise again and you'll need to either wait for the timer to go off for the node to be deleted or call CancelTimer to drop the reference count.

If you email me the code that exhibits the problem then I'll take a look, but I don't currently think there's a bug in the timer code...

Hi Len,

I debugged through my source code and see that the ref counter is dropped to 2 when the the handle that is passing into the OnTimer callback function is destroyed.

However, in my case the counter stayed at two until I have released my handle.

Could you tell me where in your source code that is doing the following statment? I didn't see that in my case.

"after OnTimer completes it drops to 1 when the release corresponding to the addref in SetTimer is called..."

Please look at the following source code:

void CCallbackTimer::HandleTimeout(
Node *pNode)
{
pNode->RemoveFromList();

try
{
pNode->OnTimer();
}
catch(...)
{
}
}

bool CCallbackTimer::CancelTimer(
Node *pNode)
{
CCriticalSection::Owner lock(m_criticalSection);

bool wasPending = false;

if (pNode->InList(m_pendingList))
{
pNode->RemoveFromList();

pNode->m_millisecondTimeout = 0;

pNode->Release();

wasPending = true;
}

return wasPending;
}


The function RemoveFromList inside the HandleTimeout function destroys the list, which make the CancelTimer function to return false. I try to call CancelTimer inside my callback OnTimer function to decrement the ref counter, but it fails because of this reason.

Dennis

Looks like you have a different version of the code to me...

void CCallbackTimer::HandleTimeout(
Node *pNode) const
{
pNode->RemoveFromList();

pNode->OnTimer();

pNode->Release();
}

Mail me and I'll send you the updated files.

Hi Len,

I have sent you an email requesting for the updated files.

In case you didn't get it, please send the files to dtan@napcosecurity.com

Thanks,

Dennis

Thanx for your perfect code, I have the same code as Dennis mentioned, If u will, pls send me the update files.

happy mid-autumn festival

best regards
liuyj

You can find the updated callback timer code on this site now; here: http://www.lenholgate.com/archives/000307.html

I see you are very helpful to all, thank you for that. I could really use a hand. I’m building socket server, which will (most of the time) broadcast messages to all connected clients based on COM Connection Pont events’ data. My Class that handles COM events will have to maintain thread safe list of all connected clients (need help please) on socket and write received data from COM to all clients (or to group of clients based on their initial request). How can I fit it in your socket server framework? What are the issues to be aware of?
Thanks,
Marko

Use the latest code.
Add connections to your collection during OnConnectionEstablished(), remove them OnSocketReleased() and dont hold a reference to them in the collection.

Do all your COM stuff in your own threads. Have the COM stuff access the collection to send stuff to the clients.

We can quote for the consultancy if you need help.

Thanks, I will try that.
Well for now it is just an idea I've been working on, but if I menage to interest our clients I will shurely contact you. But I don't belive that will be so soon.:-(

Marko,

Good luck and let me know of any bugs or problems.

Len

Hi Len,

I looked at the CThread class and notice that the handle m_hThread is created with using _beginthreadex (...) of c/c++ , but termination of the thread is done with the function TerminateThread(...) of API. So why?

Thanks in advance.

Val

Hi Len,

I looked at the CThread class and notice that the handle m_hThread is created with using _beginthreadex (...) of c/c++ , but termination of the thread is done with the function TerminateThread(...) of API. So why?

Thanks in advance.

Val

As far as I know, there is no CRT equivalent of TerminateThread(). _endThread() and _endThreadEx() replace ExitThread().

What's more, _endThread() is called implicitly when the thread terminates so I assume that calling TerminateThread() in this situation is fine as the thread will, ultimately, call _endThread() to clean up any CRT resources that were allocated during thread start.

Leave a comment