Introduction
This article shows you how to serialize a class or standard variable over a TCP/IP socket connection. It shows an example of how to setup the TCP/IP connection, setup other needed classes, and send/receive data over the socket.
I pulled from the MFC class CSocketFile
. As you may know, CSocketFile
lets you send and receive data to/from a network connection using a CArchive
. The drawback is that the implementation of CSocket
that is used has 16 bit code in it - not good for any decent application.
So I basically re-wrote them using CBlockingSocket
(instead of CSocket
) which uses 32 bit code and is better optimized. This allows you to attach a CArchive
to an open CSocketFile
and then serialize data to and from it (thus sending an receiving the data across the network).
Details
Here are the basic steps:
- Create and connect a
CBlockingSocket
object to the computer you want to send/receive data with
- Create a
CBlockingSocketFile
and attach it to the CBlockingSocket
object you created in step 1 above.
- Create a
CArchive
object and attach it to the CBlockingSocketFile
object you created in step 2 above.
NOTE: You must create 1 CArchive
for sending and 1 for receiving.
- Send your data or classes using the
CArchive
object created in step 3. You can send any serializable class or raw variables.
VERY IMPORTANT NOTE: make sure you flush the CArchive
object after you�re done sending data. This ensures all data is written across the network and tells the socket at the other end to go ahead and receive it.
- Close out the
CArchive
objects and the CBlockingSocket
object. NOTE: Don�t close the CBlockingSocketFile
object or it will assert.
Example code
CSockAddr sockAddr("127.0.0.1", SERVER_PORT);
CBlockingSocket socket; socket.Create();
socket.Connect(LPSOCKADDR(sockAddr));
CBlockingSocketFile sockFile(&socket);
CArchive arSend(&sockFile, CArchive::store );
CArchive arRecv(&sockFile, CArchive::load);
unsigned int uiCommand = 9;
CString strText("Some text to send");
arSend << uiCommand;
arSend.Flush();
strText.Serialize(arSend);
arSend.Flush();
strText.Serialize(arRecv);
MessageBox(LPCTSTR(strText), "Response from socket", MB_OK);
arSend.Close();
arRecv.Close();
socket.Close();
Conclusion
That�s basically it. Of course, I�m making one assumption that there�s a listening socket on the other end ready to send/receive the data. For convenience I�ve added an appendix below with the code to setup a listening (server) socket and receive the data then send an acknowledgment.
In the future I may derive from CArchive
and add functionality to make this whole process even easier, but for now I think this is pretty straight forward. Enjoy and happy coding!
Appendix A � Setup a listening (server) socket
CBlockingSocket listenSocket;
CSockAddr saServer;
CBlockingSocket clientSocket;
CSockAddr clientSA;
UINT uiCommand;
CString strText;
try{
CSockAddr saServer(INADDR_ANY, SERVER_PORT);
listenSocket.Create();
listenSocket.Bind(saServer);
listenSocket.Listen();
}catch(CBlockingSocketException *e) {
listenSocket.Cleanup();
return;
}
if(!listenSocket.Accept(clientSocket, clientSA)){
DEBUG_LOG2("CScheduler::run(): Accept failed with code: ",
WSAGetLastError());
}
CBlockingSocketFile sockFile(&clientSocket);
CArchive arSend(&sockFile, CArchive::store);
CArchive arRecv(&sockFile, CArchive::load);
arRecv >> uiCommand;
strText.Serialize(arRecv);
strText = �Integer and text received�;
strText.Serialize(arSend);
arSend.Flush();
arSend.Close();
arRecv.Close();
clientSocket.Close();