0

我正在使用多线程技术编写服务器。

这个想法是:

-当客户端连接时,我将使用套接字(m_Server)来接受。- 接受后,我将使用另一个端口 (t_Socket[i]) 与该客户端进行通信。就这么简单。但是我花了大约一周的时间才走到这一步(因为我对套接字有一点了解,而我之前对多线程一无所知)。

这是我在服务器上的代码:

#include "stdafx.h"
#include "testServer.h"
#include "afxsock.h"
#include "conio.h"
#include "Player.h"
#include <stdio.h>
#include "../functions.h"
#include <iostream>
using namespace std;

#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define MAX_THREADS 1 
CSocket *p_Socket=new CSocket[MAX_THREADS];

CWinApp theApp;
int count=0;

DWORD WINAPI MyThreadFunction(LPVOID lpParam)
{   
    int i=count;
    cout<<"Send : ";
    m_Send(p_Socket[i]);

    return 1;
}

int m_Send(CSocket &m_Socket)
{

    char Msg[100];
    int MsgSize;
    cin.getline(Msg,100);
    MsgSize=strlen(Msg);
    m_Socket.Send(&MsgSize,sizeof(int));
    m_Socket.Send(Msg,MsgSize);

    return MsgSize;
}

int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;

    HMODULE hModule = ::GetModuleHandle(NULL);

    if (hModule != NULL)
    {

        if (!AfxWinInit(hModule, NULL, ::GetCommandLine(), 0))
        {
            _tprintf(_T("Fatal Error: MFC initialization failed\n"));
            nRetCode = 1;
        }
        else
        {

            if(AfxSocketInit()==false)
            {
                cout<<"Initialize Library Failed"<<endl;
                return false;
            }

            int playerIndex=0;

                    CSocket m_Server;
            HANDLE hThreadArray[MAX_THREADS];
            DWORD dwThreadIdArray[MAX_THREADS];

            if(m_Server.Create(5770)==0) 
            {
                cout<<"Can not create Socket"<<endl;
                cout<<m_Server.GetLastError();
            }
            else
            {
                cout<<"Successfully initialize server"<<endl;
            }

            m_Server.Listen(5);

            for(int i=0;i<MAX_THREADS;i++)
            {
                if(m_Server.Accept(p_Socket[i]))
                {
                    cout<<"Player "<<i+1<<" connected!"<<endl;
                }
            }
            for(int i=0;i<MAX_THREADS;i++)
            {
                hThreadArray[i]=CreateThread(
                    NULL,                   
                    0,                      
                    MyThreadFunction,       
                    NULL,                   
                    0,                      
                    dwThreadIdArray);   
                //m_Send(p_Socket[i]); (1)
                count++;
            }
            WaitForMultipleObjects(MAX_THREADS, hThreadArray, TRUE, INFINITE);


            for(int i=0;i<MAX_THREADS;i++)
            {
                p_Socket[i].Close();
            }
            m_Server.Close();
            cout<<"Close all connections"<<endl;
            getch();
        }
    }
    else
    {
        _tprintf(_T("Fatal Error: GetModuleHandle failed\n"));
        nRetCode = 1;
    }
    return nRetCode;
}

问题是 :

-m_Server 接受连接后。多线程函数中的 p_Socket 没有收到正确的连接。

-但是,看看我用数字 (1) 写评论的那一行: //m_Send(p_Socket[i]); (1)。如果我运行该行而不是 CreateThread 行,程序会运行良好。但这会使我的程序变成单线程的。

顺便说一句,我将 MAX_THREADS 设置为 1,因为我想在最简单的情况下测试代码。我认为我的代码中的问题是 p_Socket[i] 无法传递给多线程函数。

我已经搜索了近 2 天的解决方案。所以我决定在这里发布一个问题,希望有人能看看它。

感谢您阅读我的问题,并对我的英语不好感到抱歉。

4

1 回答 1

0

一个大问题是您使用“计数”全局来将数组索引传递给处理程序线程。那是错误的,而且行不通。

不要将“dwThreadIdArray”作为 CreateThread API 中的最后一个参数传递,而是传入计数器“i”。

此外,您的服务器的整体结构是非典型的。通常,Accept() 循环永远运行,并在 Accept() 返回后立即启动客户端<>服务器处理程序线程,将套接字句柄/指针作为最后一个 void* 参数传递。您的代码似乎在等待,运行一个 for 循环,直到 MAX_THREADS 客户端连接,然后再在另一个循环中创建处理程序线程。这是您的预期行为吗?

于 2013-06-10T04:17:18.463 回答