C 线程采用插座参数

C++ Threading which takes a SOCKET parameter

本文关键字:插座 参数 线程      更新时间:2023-10-16

我目前正在研究我的高级项目,并且该项目几乎完成了,但是我需要在2010年在VisualStudio 2010中实现多线程,而该项目不支持C 11。因此,我将其用作多线程的来源(由我的讲师建议)在如何用插座实现它的情况下,我完全丢失了。

我的问题是如何将我已经编码的套接字与多线程使用。以下是我到目前为止所拥有的。

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 

要在线程中运行的代码需要在您传递给CreateThread()Sender()函数内。因此,这将是您的所有插座调用(WSAStartup()WSACleanup()除外,只能称呼一次)。

类似的东西:

DWORD WINAPI Sender( LPVOID lpParam)
{ 
    // Make sure there is a console to receive output results. 
    HANDLE hStdout = GetStdHandle(STD_OUTPUT_HANDLE);
    if( hStdout == INVALID_HANDLE_VALUE )
        return 1;
    HOSTENT* Host = gethostbyname("smtp.com");
    if (!Host)
    {
        cout << "Unable to resolve smtp.com" << endl;
        return 1;
    }
    //Creates the socket object named "soc(Connection"
    SOCKET socConnection = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
    if (socConnection == INVALID_SOCKET)
    {
        cout << "Socket Failed" << endl;
        return 1;
    }
    SOCKADDR_IN Addr = {0};
    Addr.sin_family = AF_INET;
    Addr.sin_addr = * (in_addr*) Host->h_addr_list[0];
    Addr.sin_port = htons(25);
    if (connect(socConnection, (SOCKADDR*)&Addr, sizeof(Addr)) == SOCKET_ERROR)
    {
        cout << "Connection Failed" << endl;
        closesocket(socConnection);
        return 1;
    }
    ...
    closesocket(socConnection);
    return 0; 
} 
int main()
{
    WSADATA wsaData; // Creates wsaData object
    WSAStartup(MAKEWORD(2, 2), &wsaData); //Initializes Winsock
    DWORD dwThreadId;
    HANDLE hThread = CreateThread( 
        NULL,                   // default security attributes
        0,                      // use default stack size  
        &Sender,                // thread function name
        NULL,                   // argument to thread function 
        0,                      // use default creation flags 
        &dwThreadId);
    ...
    WaitForSingleObject(hThread, INFINITE);
    DWORD ExitCode = 0;
    GetExitCodeThread(hThread, &ExitCode);
    CloseHandle(hThread);
    if (ExitCode != 0)
    {
        ...
    }
    ...
    WSACleanup();
    return 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("%dn", result0);
    // TODO: Network Cleanup (WSACleanup)
    return 0;
}