Sign Up

Sign Up to our social questions and Answers Engine to ask questions, answer people’s questions, and connect with other people.

Have an account? Sign In

Have an account? Sign In Now

Sign In

Login to our social questions & Answers Engine to ask questions answer people’s questions & connect with other people.

Sign Up Here

Forgot Password?

Don't have account, Sign Up Here

Forgot Password

Lost your password? Please enter your email address. You will receive a link and will create a new password via email.

Have an account? Sign In Now

You must login to ask a question.

Forgot Password?

Need An Account, Sign Up Here

Please briefly explain why you feel this question should be reported.

Please briefly explain why you feel this answer should be reported.

Please briefly explain why you feel this user should be reported.

Sign InSign Up

The Archive Base

The Archive Base Logo The Archive Base Logo

The Archive Base Navigation

  • SEARCH
  • Home
  • About Us
  • Blog
  • Contact Us
Search
Ask A Question

Mobile menu

Close
Ask a Question
  • Home
  • Add group
  • Groups page
  • Feed
  • User Profile
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Buy Points
  • Users
  • Help
  • Buy Theme
  • SEARCH
Home/ Questions/Q 8177385
In Process

The Archive Base Latest Questions

Editorial Team
  • 0
Editorial Team
Asked: June 6, 20262026-06-06T23:29:42+00:00 2026-06-06T23:29:42+00:00

I’m trying to create an IOCP TCP client and my code looks as follows:

  • 0

I’m trying to create an IOCP TCP client and my code looks as follows:

TCPClient.h:

#pragma once

typedef struct 
{ 
    WSAOVERLAPPED Overlapped; 
    SOCKET Socket; 
    WSABUF wsaBuf; 
    char Buffer[1024];
    DWORD Flags;
    DWORD BytesSent;
    DWORD BytesToSend;
} PER_IO_DATA, * LPPER_IO_DATA; 

class TCPClient
{
public:
    TCPClient();
    ~TCPClient();

    bool Connect(const std::string strIpAddress, UINT32 uPort);
    bool Disconnect();
    bool SendCommand(const std::string strCommandName);
    bool ReceiveResponse();

private:
    static DWORD WINAPI ClientWorkerThread(LPVOID lpParameter);

private:
    SOCKET m_socket;
    PER_IO_DATA *m_pPerIoData;
};

TCPClient.cpp:

#include "StdAfx.h"
#include "TCPClient.h"

TCPClient::TCPClient() :
    m_pPerIoData(NULL)
{
}

TCPClient::~TCPClient()
{
}

bool TCPClient::Connect(const std::string strIpAddress, UINT32 uPort)
{
    WSADATA wsaData;
    if (WSAStartup(MAKEWORD(2, 2), &wsaData) != NO_ERROR)
        return false;

    HANDLE hCompletionPort = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);
    if (!hCompletionPort)
        return false;

    SYSTEM_INFO systemInfo;
    GetSystemInfo(&systemInfo);

    for (DWORD dwIndex = 0; dwIndex < systemInfo.dwNumberOfProcessors; dwIndex++)
    {
        HANDLE hThread = CreateThread(NULL, 0, ClientWorkerThread, hCompletionPort, 0, NULL);
        CloseHandle(hThread);
    }

    m_socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
    if (m_socket == INVALID_SOCKET)
    {
        WSACleanup();

        return false;
    }

    sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(strIpAddress.c_str());
    server.sin_port = htons(uPort);

    CreateIoCompletionPort((HANDLE)m_socket, hCompletionPort, 0, 0);

    if (WSAConnect(m_socket, (LPSOCKADDR)&server, sizeof(server), NULL, NULL, NULL, NULL) == SOCKET_ERROR)
    {
        WSACleanup();

        return false;
    }

    return true;
}

bool TCPClient::Disconnect()
{
    if (m_socket)
        closesocket(m_socket);

    WSACleanup();

    return true;
}

bool TCPClient::SendCommand(const std::string strCommandName)
{
    m_pPerIoData = new PER_IO_DATA;
    ZeroMemory(m_pPerIoData, sizeof(PER_IO_DATA));

    strcpy(m_pPerIoData->Buffer, strCommandName.c_str());

    m_pPerIoData->Overlapped.hEvent = WSACreateEvent();
    m_pPerIoData->Socket = m_socket;
    m_pPerIoData->wsaBuf.buf = m_pPerIoData->Buffer;
    m_pPerIoData->wsaBuf.len = strlen(m_pPerIoData->Buffer);
    m_pPerIoData->BytesToSend = m_pPerIoData->wsaBuf.len;

    DWORD dwNumSent;
    if (WSASend(m_socket, &(m_pPerIoData->wsaBuf), 1, &dwNumSent, 0, &(m_pPerIoData->Overlapped), NULL) == SOCKET_ERROR)
    {
        if (WSAGetLastError() != WSA_IO_PENDING)
        {
            delete m_pPerIoData;
            return 0;
        }
    }

    while (TRUE)
        Sleep(1000);

    return true;
}

bool TCPClient::ReceiveResponse()
{
    return true;
}

DWORD WINAPI TCPClient::ClientWorkerThread(LPVOID lpParameter)
{
    HANDLE hCompletionPort = (HANDLE)lpParameter;
    DWORD NumBytesRecv = 0;
    ULONG CompletionKey;
    LPPER_IO_DATA PerIoData;

    while (GetQueuedCompletionStatus(hCompletionPort, &NumBytesRecv, &CompletionKey, (LPOVERLAPPED*)&PerIoData, INFINITE))
    {
        if (!PerIoData)
            continue;

        if (NumBytesRecv == 0)
        {
            std::cout << "Server disconnected!\r\n\r\n";
        }
        else
        {
            // use PerIoData->Buffer as needed...
            std::cout << std::string(PerIoData->Buffer, NumBytesRecv);

            PerIoData->wsaBuf.len = sizeof(PerIoData->Buffer);
            PerIoData->Flags = 0;

            if (WSARecv(PerIoData->Socket, &(PerIoData->wsaBuf), 1, &NumBytesRecv, &(PerIoData->Flags), &(PerIoData->Overlapped), NULL) == 0)
                continue;

            if (WSAGetLastError() == WSA_IO_PENDING)
                continue;
        }

        closesocket(PerIoData->Socket);
        delete PerIoData;
    }

    return 0;
}

main.cpp:

#include "stdafx.h"
#include "TCPClient.h"

int main()
{
    TCPClient client;

    client.Connect("127.0.0.1", 8888);

    client.SendCommand("Hello command\r\n");

    return 0;
}

My use of “m_pPerIoData” is clearly wrong because I’m newing every time I do SendCommand() and not deleting it properly.

  • Q1. Where should I do m_pPerIoData = new PER_IO_DATA?
  • Q2. Does it make sense to have a pointer to PER_IO_DATA as a member variable?

Edit 2:

I’ve done some renaming (Client -> Connection) to my existing code above because it was confusing me.

Some background:

  • I’m creating a DLL that is used to control an ECR (Electronic Cash Register) device connected via LAN (or serial port).
  • The DLL provides an easy-to-use interfaces such as Connect(), Disconnect() and also some ECR specific commands including Logon(), Logoff(), ReadCard() etc.
  • (Probably overkill for my application but…) I’d like to make use of IOCP in my DLL to send/receive data to/from ECR asynchronously.

My top level class looks something like this:

#pragma once

#include "Connection.h"
#include "Uncopyable.h"
#include "ConnectionFactory.h"
#include "CommandName.h"

class Ecr : private Uncopyable
{
public:
    Ecr(const std::string& rstrConnectionInfo)
        : m_spConnection(ConnectionFactory::CreateConnection(rstrConnectionInfo))
    {
        //Initialise();
    }

    ~Ecr()
    {
        //Shutdown();
    }

    bool Initialise()
    {
        if (!m_spConnection)
            return false;

        m_spConnection->Initialise();

        return true;
    }

    bool Shutdown()
    {
        if (!m_spConnection)
            return false;

        m_spConnection->Shutdown();

        return true;
    }

    bool Connect()
    {
        if (!m_spConnection)
            return false;

        if (!m_spConnection->Connect())
            return false;

        return true;
    }

    bool Disconnect()
    {
        m_spConnection->Disconnect();

        return true;
    }

    bool Logon(const std::vector<BYTE>& rvecCommandOptions)
    {
        m_spConnection->SendCommand(CommandName::Logon(), rvecCommandOptions);

        return true;
    }

    bool Logoff()
    {
        m_spConnection->SendCommand(CommandName::Logoff());

        return true;
    }

    // ... more commands follow.

private:
    ConnectionPtr m_spConnection;
};

And I’ve got TcpConnection class which is created by the ECR class and does all the hard work. Both Ecr and Connection classes are uncopyable.

Connection.h:

#pragma once

#include "Uncopyable.h"

class CommandName;

class Connection : private Uncopyable
{
public:
    Connection(const std::string& rstrConnectionInfo);
    virtual ~Connection();

    virtual bool Initialise() = 0;
    virtual bool Shutdown() = 0;
    virtual bool Connect() = 0;
    virtual bool Disconnect() = 0;
    virtual bool SendCommand(const CommandName& rCommandName, const std::vector<BYTE>& rvecCommandOptions) = 0;
    virtual bool ReceiveResponse() = 0;

    bool SendCommand(const CommandName& rCommandName);

private:
    std::string m_strConnectionInfo;
};

typedef std::tr1::shared_ptr<Connection> ConnectionPtr;

TcpConnection.h:

#pragma once
#include "connection.h"

class TcpConnection : public Connection
{
public:
    TcpConnection(const std::string& rstrConnectionInfo);
    ~TcpConnection();

    // Connection
    bool Initialise();
    bool Shutdown();
    bool Connect();
    bool Disconnect();
    bool SendCommand(const CommandName& rCommandName, const std::vector<BYTE>& rvecCommandOptions);
    bool ReceiveResponse();

    static DWORD WINAPI WorkerThread(LPVOID lpParam);

private:
    SOCKET m_socket;
    HANDLE m_hIocp;
};

TcpConnection.cpp:

#include "StdAfx.h"
#include "TcpConnection.h"
#include "CommandBuilderTcp.h"

TcpConnection::TcpConnection(const std::string& rstrConnectionInfo)
    : Connection(rstrConnectionInfo)
    , m_socket(INVALID_SOCKET)
    , m_hIocp(INVALID_HANDLE_VALUE)
{
    WSADATA wsaData;
    WSAStartup(MAKEWORD(2, 2), &wsaData);

    m_socket = WSASocket(AF_INET, SOCK_STREAM, IPPROTO_TCP, NULL, 0, WSA_FLAG_OVERLAPPED);
}

TcpConnection::~TcpConnection()
{
}

bool TcpConnection::Initialise()
{
    // Set up threads for using IOCP.

    m_hIocp = CreateIoCompletionPort(INVALID_HANDLE_VALUE, NULL, 0, 0);

    SYSTEM_INFO systemInfo;
    GetSystemInfo(&systemInfo);

    for (DWORD dwIndex = 0; dwIndex < systemInfo.dwNumberOfProcessors; dwIndex++)
    {
        HANDLE hThread = CreateThread(NULL, 0, WorkerThread, m_hIocp, 0, NULL);
        CloseHandle(hThread);
    }

    CreateIoCompletionPort((HANDLE)m_socket, m_hIocp, 0, 0);

    return true;
}

bool TcpConnection::Shutdown()
{
    // Release threads.

    return true;
}

bool TcpConnection::Connect()
{
    if (m_socket)
        return true;

    // Hard-coding IP address and port number for now.
    sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr("10.0.9.80");
    server.sin_port = htons(22000);

    WSAConnect(m_socket, (LPSOCKADDR)&server, sizeof(server), NULL, NULL, NULL, NULL);

    return true;
}

bool TcpConnection::Disconnect()
{
    if (m_socket)
        closesocket(m_socket);

    WSACleanup();

    return true;
}

bool TcpConnection::SendCommand(const CommandName& rCommandName, const std::vector<BYTE>& rvecCommandOptions)
{
    // Build full command from rCommandName and rvecCommandOptions and send to server.
    return true;
}

bool TcpConnection::ReceiveResponse()
{
    return true;
}

DWORD WINAPI TcpConnection::WorkerThread(LPVOID lpParam)
{
    // Call GetQueuedCompletionStatus in a loop
    return 0;
}

A host application then creates a DLL instance per ECR device:

Ecr ecr("ipaddress+port");

ecr.Initialise(); // Or do this in Ecr's ctor?

ecr.Connect();

BYTE arrCommandOptions[] = {0x00, 0x00, 0x00, 0x01, 0x18, 0xA6, 0x00, 0x01, 0x49, 0x08, 0x26};
std::vector<BYTE> vecCommandOptions(arrCommandOptions, arrCommandOptions + sizeof(arrCommandOptions) / sizeof(arrCommandOptions[0]));
ecr.Logon(vecCommandOptions);

ecr.Logoff();

ecr.Disconnect();

ecr.Shutdown(); // Or do this in Ecr's dtor?

return 0;

I want all the IOCP related stuff at the TcpConnection level, not the Ecr level because I don’t want Ecr to care how data transmission is done underneath.

Is my idea not going to work?

  • 1 1 Answer
  • 0 Views
  • 0 Followers
  • 0
Share
  • Facebook
  • Report

Leave an answer
Cancel reply

You must login to add an answer.

Forgot Password?

Need An Account, Sign Up Here

1 Answer

  • Voted
  • Oldest
  • Recent
  • Random
  1. Editorial Team
    Editorial Team
    2026-06-06T23:29:46+00:00Added an answer on June 6, 2026 at 11:29 pm

    What you showed is based on the IOCP code I gave you in another question. However, that code was designed to re-use a single PER_IO_DATA instance across multiple IOCP operations on the same socket, because you were only reading in the client and only writing in the server. Now you are mixing both reading and writing in the client, so you need to adjust the worker thread to support both types of IOCP operations by merging all of the code I gave you earlier, at then add an additional flag in the PER_IO_DATA so a completed operation knows whether it was a read operation or a write operation.

    As for your questions:

    Where should I do m_pPerIoData = new PER_IO_DATA?

    It doesn’t make much sense to use a class-wide m_pPerIoData member at all. SendCommand() is creating a new PER_IO_DATA, which is fine, you would just need to delete it when a worker thread has detected that all of PER_IO_DATA::Buffer data has finished being sent or the socket has been closed.

    Does it make sense to have a pointer to PER_IO_DATA as a member variable?

    Not for the write operations, no. You could have a single class member for reading, though. Unless SendCommand() creates a new PER_IO_DATA when it is ready to read a single response. The worker thread would then need to delete it when the full response has been received or the socket has been closed.

    • 0
    • Reply
    • Share
      Share
      • Share on Facebook
      • Share on Twitter
      • Share on LinkedIn
      • Share on WhatsApp
      • Report

Sidebar

Related Questions

Basically, what I'm trying to create is a page of div tags, each has
I'm trying to create an if statement in PHP that prevents a single post
I have a .ini file as follows: [playlist] numberofentries=2 File1=http://87.230.82.17:80 Title1=(#1 - 365/1400) Example
I am trying to understand how to use SyndicationItem to display feed which is
link Im having trouble converting the html entites into html characters, (&# 8217;) i
I have a string like this: La Torre Eiffel paragonata all&#8217;Everest What PHP function
I am trying to render a haml file in a javascript response like so:
I have this code to decode numeric html entities to the UTF8 equivalent character.
I would like to run a str_replace or preg_replace which looks for certain words
I'm parsing an RSS feed that has an &#8217; in it. SimpleXML turns this

Explore

  • Home
  • Add group
  • Groups page
  • Communities
  • Questions
    • New Questions
    • Trending Questions
    • Must read Questions
    • Hot Questions
  • Polls
  • Tags
  • Badges
  • Users
  • Help
  • SEARCH

Footer

© 2021 The Archive Base. All Rights Reserved
With Love by The Archive Base

Insert/edit link

Enter the destination URL

Or link to existing content

    No search term specified. Showing recent items. Search or use up and down arrow keys to select an item.