TCP服务器接收多个客户端连接

LRESULT CNetDogSDlg::OnXAcceptSocket(WPARAM wParam,LPARAM lParam)
{
    int acc_sin_len;        // Accept socket address length
    SOCKADDR_IN acc_sin;    // Accept socket address - internet style
    SOCKET ConnectSocket;
    SOCKET ListenSocket;
    TEMPSOCKET ts;

    UpdateComStatus();

    ListenSocket = m_data.GetListenSocket();

    if( WSAGETSELECTERROR( lParam ) != 0 ) {
        ShowNetMonitorMsg( _T("在侦听 Socket 上发生错误.") );
        // Cancel any further notifications.
        //WSAAsyncSelect( ListenSocket,GetSafeHwnd(),0,0 );
        //closesocket( ListenSocket );
        //m_data.SetListenSocket( INVALID_SOCKET );
        //m_data.SetListenSocketStatus( FALSE,m_txtPortStatus,m_btnListen );
        return 0;
    }

    switch( WSAGETSELECTEVENT( lParam ) ) {
        case FD_ACCEPT:
            ShowNetMonitorMsg( _T("有客户申请连接...") );

            // Accept the incoming connection.
            acc_sin_len = sizeof( acc_sin );
            ConnectSocket = accept( ListenSocket,( struct sockaddr FAR * )&acc_sin,( int FAR * )&acc_sin_len );
            if( ConnectSocket == INVALID_SOCKET ) {
                ShowNetMonitorMsg( _T("创建客户连接 Socket 失败.") );
                return 0;
            }

            // Send main window a WSA_READ when either data is pending on
            // the socket (FD_READ) or the connection is closed (FD_CLOSE)
            if( WSAAsyncSelect( ConnectSocket,GetSafeHwnd(),UM_CONNECT,FD_READ | FD_WRITE | FD_CLOSE ) == SOCKET_ERROR ) {
                ShowNetMonitorMsg( _T("建立客户连接 Socket 异步通信消息失败.") );
                closesocket( ConnectSocket );
                return 0;
            }

            // Get User information.
            // --------------------------------------------------
            {
                CString str,strConnectPort,strHostIP,strHostName;
                str.Format( _T("客户连接成功 - 连接到: Socket( %d ) "),ConnectSocket );
                strConnectPort.Format( _T("%d"),acc_sin.sin_port );
                strHostIP.Format( _T("%d.%d.%d.%d"),
                    acc_sin.sin_addr.S_un.S_un_b.s_b1,
                    acc_sin.sin_addr.S_un.S_un_b.s_b2,
                    acc_sin.sin_addr.S_un.S_un_b.s_b3,
                    acc_sin.sin_addr.S_un.S_un_b.s_b4
                );
                HOSTENT* pHostent = gethostbyaddr( (const char *)&(acc_sin.sin_addr),sizeof(struct in_addr),AF_INET );
                if( !pHostent ) {
                    strHostName = _T("未知");
                }
                else {
                    strHostName = pHostent->h_name;
                }
                str += _T("端口号: ");
                str += strConnectPort;
                str += _T(" 客户IP: ");
                str += strHostIP;
                str += _T(" 客户机器名: ");
                str += strHostName;
                ShowNetMonitorMsg( str );

                ts.Port = acc_sin.sin_port;
                ts.skt = ConnectSocket;
                lstrcpy( ts.UserName,strHostName );
                lstrcpy( ts.IPAddress,strHostIP );
            }
            if( !m_data.AddTempSocket( &ts ) ) {
                closesocket( ConnectSocket );
                ShowNetMonitorMsg( _T("存贮客户连接 Socket 空间不足.") );
            }
            break;
        case FD_CLOSE:
            ShowNetMonitorMsg( _T("侦听 Socket 被关闭.") );
            closesocket( ListenSocket );
            m_data.SetListenSocket( INVALID_SOCKET );
            m_data.SetListenSocketStatus( FALSE,m_txtPortStatus,m_btnListen );
            break;
        case FD_READ:
            ShowNetMonitorMsg( _T("<接收数据>消息 到达侦听 Socket.") );
            break;
        case FD_WRITE:
            ShowNetMonitorMsg( _T("<发送数据>消息 到达侦听 Socket.") );
            break;
        default:
            ShowNetMonitorMsg( _T("<未知>消息 到达侦听 Socket.") );
            break;
    }

    return 0;
}

LRESULT CNetDogSDlg::OnXConnectSocket(WPARAM wParam,LPARAM lParam)
{
    SOCKET ConnectSocket;
    CString str;
    int nRet;
    char Buf[MAX_SOCKET_BUF];

    UpdateComStatus();

    ConnectSocket = ( SOCKET )wParam;
    if( WSAGETSELECTERROR( lParam ) != 0 ) {
        str.Format(_T("在连接 Socket( %d ) 上发生错误,断开客户连接."),ConnectSocket );
        ShowNetMonitorMsg( str );
        closesocket( ConnectSocket );
        m_data.DeleteConnectSocket( ConnectSocket );
        m_data.UpdateProductInfo( m_lstProductInfo,FALSE );
        m_data.ShowUserInfo( m_lstUserInfo );
        return 0;
    }

    switch( WSAGETSELECTEVENT( lParam ) ) {
        case FD_CLOSE:
            str.Format( _T("连接在 Socket( %d )上的用户断开连接."),ConnectSocket );
            ShowNetMonitorMsg( str );
            closesocket( ConnectSocket );
            m_data.DeleteConnectSocket( ConnectSocket );
            m_data.UpdateProductInfo( m_lstProductInfo,FALSE );
            m_data.ShowUserInfo( m_lstUserInfo );
            break;
        case FD_READ:
            str.Format(_T("<接收数据>消息 到达连接 Socket( %d )."),ConnectSocket );
            ShowNetMonitorMsg( str );
            ZeroMemory( Buf,MAX_SOCKET_BUF );
            nRet = recv( ConnectSocket,Buf,MAX_SOCKET_BUF,0 );
            switch( nRet ) {
                case SOCKET_ERROR:
                    str.Format( _T("从 连接 Socket( %d ) 读取数据时发生错误."),ConnectSocket );
                    ShowNetMonitorMsg( str );
                    break;
                case 0:
                    str.Format( _T("连接 Socket( %d ) 被关闭."),ConnectSocket );
                    ShowNetMonitorMsg( str );
                    break;
                default:
                    str.Format( _T("从连接 Socket( %d ) 读取了 %d 字节数据."),ConnectSocket,nRet );
                    if( !m_data.AddXData( ConnectSocket,Buf,nRet ) ) {
                        str += _T("/r/n---------> 数据缓冲区已满,数据被丢弃.");
                    }
                    else {
                        str += _T("/r/n---------> 数据成功保存到缓冲区,等待处理.");
                    }
                    ShowNetMonitorMsg( str );
                    m_data.ParseData( this,m_lstProductInfo,m_lstUserInfo );
                    break;
            }
            break;
        case FD_WRITE:
            str.Format(_T("<发送数据>消息 到达连接 Socket( %d )."),ConnectSocket );
            ShowNetMonitorMsg( str );
            break;
        default:
            str.Format(_T("<未知>消息 到达连接 Socket( %d )."),ConnectSocket );
            ShowNetMonitorMsg( str );
            break;
    }

    return 0;
}

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要实现一个Qt TCP服务器连接多个客户端,可以使用Qt Network模块中的QTcpServer和QTcpSocket类。 首先要创建一个QTcpServer对象,并在其中的某个函数(如`incomingConnection()`)中监听新的客户端连接请求。当有新的客户端连接请求时,可以通过调用`nextPendingConnection()`函数来获得一个QTcpSocket对象,表示与该客户端连接。 接下来,可以将该QTcpSocket对象添加到一个存储所有客户端连接的容器中(如QList<QTcpSocket*>),并对其进行读写操作。可以使用`readyRead()`信号来接收客户端发送的数据,使用`write()`函数来向客户端发送数据。 当客户端连接断开时,可以使用`disconnected()`信号来处理该事件,并从存储所有客户端连接的容器中将该QTcpSocket对象移除。 以下是一个简单的示例代码: ```cpp #include <QTcpServer> #include <QTcpSocket> #include <QList> class MyServer : public QTcpServer { Q_OBJECT public: MyServer(QObject *parent = nullptr) : QTcpServer(parent) {} protected: void incomingConnection(qintptr socketDescriptor) override { QTcpSocket *clientSocket = new QTcpSocket(this); if (!clientSocket->setSocketDescriptor(socketDescriptor)) { delete clientSocket; return; } m_clients.append(clientSocket); connect(clientSocket, &QTcpSocket::readyRead, this, &MyServer::readData); connect(clientSocket, &QTcpSocket::disconnected, this, &MyServer::disconnected); } private slots: void readData() { QTcpSocket *clientSocket = static_cast<QTcpSocket*>(sender()); if (!clientSocket) { return; } QByteArray data = clientSocket->readAll(); // 处理接收到的数据 // 回复客户端 clientSocket->write("Hello, client!"); } void disconnected() { QTcpSocket *clientSocket = static_cast<QTcpSocket*>(sender()); if (!clientSocket) { return; } m_clients.removeOne(clientSocket); clientSocket->deleteLater(); } private: QList<QTcpSocket*> m_clients; }; ``` 在上面的代码中,`MyServer`继承自`QTcpServer`,并重写了`incomingConnection()`函数处理新的客户端连接请求。在该函数中,创建一个新的QTcpSocket对象表示与该客户端连接,并将其添加到存储所有客户端连接的容器中。 在`readData()`函数中,处理接收到的数据并向客户端回复数据。在`disconnected()`函数中,处理客户端断开连接的事件并将其从存储所有客户端连接的容器中移除。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值