I'm attempting to build a simple listener, preferably without a Thread, but I am lost.

I have a working listener in 'console' mode but I need one that works with MFC. It should stay open indefinately - (until I send a shutdown message)

This is my initial non-working attempt. It connects and listens OK, but the Accept() function only receives the first line sent and then freezes. (using the code as shown - while and do loops edited out)

CString	clientIP = "xxx.xxx.xxx.xxx";

CSocket hsock;
hsock.Create(port,SOCK_STREAM,clientIP);
hsock.Listen(5);

char	buf[512];

// I know this is NOT correct, but I cannot figure out hwo to make it work
//while (1) { 
  CSocket tsock;
  hsock.Accept(tsock);

  int bytes = hsock.Receive(buf,sizeof(buf),0);
//  do {
    AfxMessageBox(buf);
//  }
//}

I've read thought Micro$ confusing MFC documentation on Socket, CSocket, AsyncSocket and I come away more confused that when I started. I think I need to use Archive(), but again I get lost.

Any help would be very welcome, but please, no links to the Micro$ site.

Dani AI

Generated

Nice troubleshooting so far — 's suggestion exposed the blocking/UI problem and correctly moved to CAsyncSocket and found the real crash cause. The assertion in sockcore.cpp (Accept into an already-open socket) is a sign that a single client-instance is being reused while the peer reconnects. A more robust pattern is: create a fresh client object for each Accept, keep it in a container, and clean it up when the connection closes.

Example pattern (new per‑connection object + container):

// in server class
void MFCServer::OnAccept(int)
{
    MFCClient* p = new MFCClient(this);      // keep pointer-to-server for cleanup
    if (!Accept(*p)) { delete p; return; }
    m_clients.push_back(p);                  // preserve lifetime
    CAsyncSocket::OnAccept(0);
}

Reading and cleanup tips:

  • In the client object, loop reading until Receive() returns <= 0 (0 = graceful close, SOCKET_ERROR = check WSAGetLastError()). Guard buffer bounds and avoid using blocking UI calls inside the callback. Instead, post data to the main window (PostMessage) or enqueue it for the UI thread to consume.
  • Override OnClose to remove the client pointer from the server container and delete the object (or have the server delete it from a safe place). If you choose delete this inside OnClose, be careful — make sure no further socket callbacks will touch the instance.

Other practical tips:

  • Don’t call AfxMessageBox inside OnReceive (it blocks the message loop and can interfere with async notifications).
  • Check return values (Accept/Receive) and call WSAGetLastError() for diagnostics.
  • For devices that drop idle connections, consider an application-level heartbeat or tuned TCP keepalive so you detect and recycle stale sockets faster than the OS defaults.

This structure avoids the single‑instance race you hit, scales to multiple clients, and keeps the UI responsive while preserving the simplicity of CAsyncSocket.

Recommended Answers

All 5 Replies

What happens when you change your code to this?

char	buf[512] = "";
CSocket tsock;
if ( hsock.Accept(tsock) == 0 )
{
[INDENT]// Error
return;[/INDENT]
}
while (1) 
{[INDENT]int bytes = tsock.Receive(buf,sizeof(buf),0);
if ( bytes == 0 ) // No data read. Close the Socket.
{
[INDENT]break;[/INDENT]
}
if ( bytes == SOCKET_ERROR )
{
[INDENT]AfxMessageBox("Error";
break;[/INDENT]
}
AfxMessageBox(buf);[/INDENT]}
tsock.Close();

Thanks WolfPack. That kind-of worked. The while loop causes the, I'm busy 'hour-glass' to sit on the page but I am getting results.

It dawned on me that a listener is simply a server without a send capability. Googling for Socket Server, returned some interesting techniques. I think I may be able to get this working now. I'll post back a working solution or MORE questions. :)

My solution - with help from my Google search results...

// Initilize the Listener - (in OnNewDocument for me)
BOOL CMFCSocketDoc::OnNewDocument() {
  ..
  // #include "MFCServer.h" in .doc.h
  // declare...  MFCServer skt_server; in ...doc.h
  skt_server.Create(port#);
  skt_server.Listen();
  return true;
}

// Create 2 new classes:
class MFCServer : public CAsyncSocket {...};
// Add this function  
void MFCServer::OnAccept(int nErrorCode) {
  // #include "MFCClient.h" in .h
  // declare... MFCClient skt_client; in .h
  Accept(skt_client);
  CAsyncSocket::OnAccept(nErrorCode);
}

class MFCClient : public CAsyncSocket {...};
// Add this function
void MFCClient::OnReceive(int nErrorCode) {
  char buff[200];
  int bytes_read = Receive(buff, 200);
  buff[bytes_read] = 0;			//terminate the string

  AfxMessageBox(buff);
  CAsyncSocket::OnReceive(nErrorCode);
}

And there you have it - A simple listener without threads.
If I did something REALLY wrong, please let me know.

I'm back :)

I incorporated the above into my program and it worked - well almost.

The computer (listener) is connected to a device that closes it's socket after an idle time of 15 sec to save on network resources. In my 'console' version, when the device comes alive, data is sent and received. - no problem.

But in the MFC version, after this idle time-out period and on the next read, it creates a 'Debug Assertion Failed' popup (sockcore.cpp, Line 117). If I then click on 'Ignore', the data is read. All additional data goes through the same cycle.

So what did I do wrong?

A few hours of testing and head scratching, and I came up with a solution. Pretty simple really...

When the device closed it's socket, it attempted to reconnect but the skt_client socket was still open and the OnAccept tried to create a new client socket. So I simply closed the socket and allowed a new one to be opened.

void MFCServer::OnAccept(int nErrorCode) {
  CAsyncSocket::OnAccept(nErrorCode);
  skt_client.Close();
  Accept(skt_client);
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.