DESKTOP

Network Programming with Windows Sockets : An Alternative Thread-Safe DLL Strategy

10/10/2010 3:17:33 PM

Program 1, while typical of the way in which TLS and DllMain are combined to create thread-safe libraries, has two major weaknesses noted in the comments in the previous section. First, the state is associated with the thread rather than with the socket, so a given thread can process only one socket at a time. Second, there is the resource leak risk mentioned in the last bullet above.

An effective alternative approach to thread-safe library functions is to create a handle-like structure that is passed to every function call. The state is then maintained in the structure. The application explicitly manages the state, so you can manage multiple sockets in a thread, and you can even use the sockets with fibers (there might be one socket, or more, per fiber). Many UNIX and Linux applications use this technique to create thread-safe C libraries; the main disadvantage is that the functions require an additional parameter for the state structure.

Program 2 modifies Program 1. Notice that DllMain is not necessary, but there are two new functions to initialize and free the state structure. The send and receive functions require only minimal changes. An associated server, serverSKHA, is included in the Examples file and requires only slight changes in order to create and close the socket handle (HA denotes “handle”).

Program 2. SendReceiveSKHA: Thread-Safe DLL with a State Structure
/* SendReceiveSKHA.c -- multithreaded streaming socket. */
/* This is a modification of SendReceiveSKST.c to illustrate a */
/* different thread-safe library technique. */
/* State is preserved in a handle-like state structure rather than */
/* using TLS. This allows a thread to use several sockets at once. */
/* Messages are delimited by null characters ('\0'). */

#include "Everything.h"
#include "ClientServer.h"/* Defines MESSAGEa. */

typedef struct SOCKET_HANDLE_T {
/* Current socket state */
/* Contains "staticBuffLen" characters of residual data */
/* There may or may not be end-of-string (null) characters */
SOCKET sk;
char staticBuff[MAX_RQRS_LEN];
LONG32 staticBuffLen;
} SOCKET_HANDLE, * PSOCKET_HANDLE;

/* Functions to create and close "streaming socket handles" */
__declspec (dllexport)
PVOID CreateCSSocketHandle (SOCKET s)
{
PVOID p;
PSOCKET_HANDLE ps;

p = malloc (sizeof(SOCKET_HANDLE));
if (p == NULL) return NULL;
ps = (PSOCKET_HANDLE)p;
ps->sk = s;
ps->staticBuffLen = 0; /* Initialize buffer state */
return p;
}

__declspec (dllexport)
BOOL CloseCSSocketHandle (PSOCKET_HANDLE psh)
{
if (psh == NULL) return FALSE;
free (psh);
return TRUE;
}

__declspec(dllexport)
BOOL ReceiveCSMessage (MESSAGE *pMsg, PSOCKET_HANDLE psh)
/* Use PVOID so that calling program does not need to include the */
/* SOCKET_HANDLE definition. */
{
/* TRUE return indicates an error or disconnect */
BOOL disconnect = FALSE;
LONG32 nRemainRecv = 0, nXfer, k; /* Must be signed integers */
LPSTR pBuffer, message;
CHAR tempBuff[MAX_RQRS_LEN+1];
SOCKET sd;

if (psh == NULL) return FALSE;
sd = psh->sk;

/* This is all that's changed from SendReceiveSKST! */
message = pMsg->record;
/* Read up to the null character, leaving residual data
* in the static buffer */

for (k = 0;
k < psh->staticBuffLen && psh->staticBuff[k] != '\0'; k++) {
message[k] = psh->staticBuff[k];
} /* k is the number of characters transferred */
if (k < psh->staticBuffLen) { /* null found in buffer */
message[k] = '\0';
psh->staticBuffLen -= (k+1); /* Adjust buffer state */
memcpy (psh->staticBuff, &(psh->staticBuff[k+1]),
psh->staticBuffLen);
return TRUE; /* No socket input required */
}

/* The entire static buffer was transferred. No null found */
nRemainRecv = sizeof(tempBuff) - 1 - psh->staticBuffLen;
pBuffer = message + psh->staticBuffLen;
psh->staticBuffLen = 0;

while (nRemainRecv > 0 && !disconnect) {
nXfer = recv (sd, tempBuff, nRemainRecv, 0);
if (nXfer <= 0) {
disconnect = TRUE;
continue;
}

nRemainRecv -=nXfer;
/* Transfer to target message up to null, if any */
for (k = 0; k < nXfer && tempBuff[k] != '\0'; k++) {
*pBuffer = tempBuff[k];
pBuffer++;
}
if (k >= nXfer) { /* null not found, read more */
nRemainRecv -= nXfer;
} else { /* null has been found */
*pBuffer = '\0';
nRemainRecv = 0;
memcpy (psh->staticBuff, &tempBuff[k+1], nXfer - k - 1);
psh->staticBuffLen = nXfer -k - 1;
}
}
return !disconnect;

}

__declspec(dllexport)
BOOL SendCSMessage (MESSAGE *pMsg, PSOCKET_HANDLE psh)
{
/* Send the the request to the server on socket sd */
BOOL disconnect = FALSE;
LONG32 nRemainSend, nXfer;
LPSTR pBuffer;
SOCKET sd;

if (psh == NULL || pMsg == NULL) return FALSE;
sd = psh->sk;

pBuffer = pMsg->record;
/* Ignore Win64 conversion warning. strlen is size_t */
nRemainSend = min(strlen (pBuffer) + 1, MAX_MESSAGE_LEN);

while (nRemainSend > 0 && !disconnect) {
/* send does not guarantee that the entire message is sent */
nXfer = send (sd, pBuffer, nRemainSend, 0);
if (nXfer <= 0) {
disconnect = TRUE;
}
nRemainSend -=nXfer; pBuffer += nXfer;
}

return !disconnect;
}


 

Other  
 
Most View
Samsung Galaxy Note II In-Depth Review (Part 1)
Cloud Computing Reconsidered (Part 2)
How To Install Old Hardware Drivers On Windows 8
Windows Vista : Programming the WScript Object
The next Nexus (Part 2)
Olympus XZ-10 Super Compact Camera Review (Part 1)
Microsoft Exchange Server 2010 : Working with Active Mailbox Databases (part 3) - Recovering Deleted Mailboxes , Recovering Deleted Items from Mailbox Databases
Windows Server 2008 and Windows Vista : Backing Up and Restoring GPOs (part 2)
Migrating to Windows Small Business Server 2011 : Performing Post-Migration Tasks (part 2)
Digitize Music, Video And Photos For Free (Part 2)
REVIEW
- First look: Apple Watch

- First look: Apple MacBook (12-inch Retina display)
VIDEO TUTORIAL
- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 1)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 2)

- How to create your first Swimlane Diagram or Cross-Functional Flowchart Diagram by using Microsoft Visio 2010 (Part 3)
Popular Tags
Microsoft Access Microsoft Excel Microsoft OneNote Microsoft PowerPoint Microsoft Project Microsoft Visio Microsoft Word Active Directory Biztalk Exchange Server Microsoft LynC Server Microsoft Dynamic Sharepoint Sql Server Windows Server 2008 Windows Server 2012 Windows 7 Windows 8 Adobe Indesign Adobe Flash Professional Dreamweaver Adobe Illustrator Adobe After Effects Adobe Photoshop Adobe Fireworks Adobe Flash Catalyst Corel Painter X CorelDRAW X5 CorelDraw 10 QuarkXPress 8 windows Phone 7 windows Phone 8 BlackBerry Android Ipad Iphone iOS
Top 10
C# 2010 and the .NET 4 Platform : Understanding the ASP.NET Profile API (part 4) - Grouping Profile Data and Persisting Custom Objects
C# 2010 and the .NET 4 Platform : Understanding the ASP.NET Profile API (part 3) - Accessing Profile Data Programmatically
C# 2010 and the .NET 4 Platform : Understanding the ASP.NET Profile API (part 2) - Defining a User Profile Within Web.config
C# 2010 and the .NET 4 Platform : Understanding the ASP.NET Profile API (part 1) - The ASPNETDB.mdf Database
C# 2010 and the .NET 4 Platform : The Role of the sessionState Element - Storing Session Data in the ASP.NET Session State Server, Storing Session Data in a Dedicated Database
C# 2010 and the .NET 4 Platform : ASP.NET State Management Techniques - Understanding Cookies
BMW 220i CONVERTIBLE :Blend of poise and power
VOLKSWAGEN JETTA 1.4 HIGHLINE : A Volkswagen for mass market
PEUGEOT 508 : Plush Peugeot
First look : Panasonic Lumix DMC-GF7