采用SOCKET参数的C ++ Threading

时间:2014-03-07 01:40:05

标签: c++ multithreading sockets

我目前正在开展高级项目,项目已基本完成,但我需要在不支持C ++ 11的VisualStudio 2010中实现多线程。因此我使用它作为多线程的来源(由我的导师建议)http://msdn.microsoft.com/en-us/library/windows/desktop/ms682516(v=vs.85).aspx,我完全迷失了如何用SOCKET实现它。

我的问题是我如何使用已编码的多线程套接字。以下是我到目前为止的情况。

typedef struct SenderData {

SOCKET socConnection;

} SENDERDATA, *PSENDERDATA;


DWORD WINAPI SenderThreadFunction( LPVOID lpParam){ 
HANDLE hStdout;
PSENDERDATA pDataArray;

TCHAR msgBuf[BUF_SIZE];
size_t cchStringSize;
DWORD dwChars;

// Make sure there is a console to receive output results. 

hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
if( hStdout == INVALID_HANDLE_VALUE )
    return 1;

// Cast the parameter to the correct data type.
// The pointer is known to be valid because 
// it was checked for NULL before the thread was created.

pDataArray = (PSENDERDATA)lpParam;

return 0; 
} 

此函数具有在telnet中启动会话并从文件

发送消息的所有命令
DWORD WINAPI Sender(LPVOID lpParam){ 
}

以下创建连接,我最初在main()中创建了连接但不确定现在放在哪里

WSADATA wsaData; // Creates wsaData object
WSAStartup(MAKEWORD(2, 2), &wsaData); //Initializes Winsock
//Creates the socket object named "soc(Connection"
SOCKET socConnection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

SOCKADDR_IN Addr;
HOSTENT* Host = gethostbyname("smtp.com");
Addr.sin_addr.s_addr = inet_addr(inet_ntoa(*(in_addr*)Host->h_addr_list[0]));
Addr.sin_family = AF_INET;
Addr.sin_port = htons(25);

如果我没有使用线程

,这将在main()中调用
if (connect(Connection, (SOCKADDR*)&Addr, sizeof(SOCKADDR_IN)) == SOCKET_ERROR)
    cout << "Connection Failed" << endl;    

在main()中执行以下代码时,如何将以前的代码置于启动状态? 我是C ++的新手,我非常感谢任何帮助。提前谢谢。

hThreadArray[0] = CreateThread( 
        NULL,                   // default security attributes
        0,                      // use default stack size  
        Sender,       // thread function name
        pDataArray[0],          // argument to thread function 
        0,                      // use default creation flags 
        &dwThreadIdArray[0]);   // returns the thread identifier 

2 个答案:

答案 0 :(得分:0)

要在线程中运行的代码需要位于要传递给Sender()的{​​{1}}函数内。这就是你的所有套接字调用(CreateThread()WSAStartup()除外,只应调用一次)。

这样的事情:

WSACleanup()

答案 1 :(得分:0)

还有一些帮助,你如何将线程封装到类中以获得真正面向对象和更可重用的代码:

#include <windows.h>
#include <stdio.h>
#include <assert.h>

class CThread
{
public:
    void Start()
    {
        assert(!m_Handle);
        DWORD thread_id;
        m_Handle = ::CreateThread(NULL, 0, StaticThreadProc, this, 0, &thread_id);
        // this should be a fatal error/exit instead of a simple assert...
        assert(m_Handle);
    }

    void Join()
    {
        assert(m_Handle);
        ::WaitForSingleObject(m_Handle, INFINITE);
    }

protected:
    virtual void Execute() = 0;

    CThread() : m_Handle(NULL) {}
    ~CThread()
    {
        if (m_Handle)
        {
            Join();
            ::CloseHandle(m_Handle);
            m_Handle = NULL;
        }
    }

private:
    static DWORD WINAPI StaticThreadProc(LPVOID param)
    {
        CThread* thread = reinterpret_cast<CThread*>(param);
        thread->Execute();
        return 0;
    }

private:
    HANDLE m_Handle;
};

class CMyThread : public CThread
{
public:
    CMyThread()
    {
        m_Sock = NULL;
        m_Whatever = 0;
        m_OtherParam = 0;
        m_Result = 0;
    }

    // Use this to initialize the parameters for your thread before starting it...
    // You could initialize from your constructor too if you wouldn't store your
    // threads in an array by value...
    void Init(SOCKET sock, int whatever_parameter_you_need, int other_param)
    {
        m_Sock = sock;
        m_Whatever = whatever_parameter_you_need;
        m_OtherParam = other_param;
    }

    int GetResult() const
    {
        return m_Result;
    }

protected:
    virtual void Execute() override
    {
        // Use m_Sock, m_Whatever, m_OtherParam ....
        // Fill out m_Result before returning from the Execute() method of the thread.

        // You can also create the socket inside the thread if you want,
        // noone forces you to pass it here as an init parameter.
        m_Result = 5;
    }

private:
    SOCKET m_Sock;
    int m_Whatever;
    int m_OtherParam;
    int m_Result;
};


int main()
{
    // TODO: network init (WSAStartup)

    const int NUM_THREADS = 3;
    CMyThread threads[NUM_THREADS];

    // 1. Initializing threads with incoming parameters to work with
    for (int i=0; i<NUM_THREADS; ++i)
    {
        //threads[i].Init(...)
    }

    // 2. Starting threads
    for (int i=0; i<NUM_THREADS; ++i)
        threads[i].Start();

    // 3. Waiting for threads to finish...
    for (int i=0; i<NUM_THREADS; ++i)
        threads[i].Join();

    // 4. Processing results if needed
    int result0 = threads[0].GetResult();
    printf("%d\n", result0);

    // TODO: Network Cleanup (WSACleanup)

    return 0;
}