weixin_43599456
真无聊一人
2019-12-12 18:05

c++,socket编程实现简易聊天系统,客户端一直连不上服务端,connect返回错误10014

  • c++

客户端

//建立线程

DWORD WINAPI ConnectThreadFunc(LPVOID pParam) {

    //初始化
    WSAData wsData;
    if (!AfxSocketInit(&wsData))
    {
        AfxMessageBox(_T("Socket 库初始化出错!"));
        return false;
    }


    CMFCApplication1View *pChatClient = (CMFCApplication1View*)pParam;
    ASSERT(pChatClient != NULL);

    //新建一个socket
    pChatClient->ConnectSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);


    if (INVALID_SOCKET==pChatClient->ConnectSock ) {
        AfxMessageBox(_T("创建socket失败!"));
        return FALSE;
    }
    AfxMessageBox(_T("成功创建socket"));

    //获取端口
    CString ServeIp;
    pChatClient->GetDlgItemText(IDC_SERVEID_INPUT, ServeIp); //取服务端的IP地址
    int SPort = pChatClient->GetDlgItemInt(IDC_SERVEPORT_INPUT); //获取端口
    if (SPort <= 0 || SPort > 65535) {
        AfxMessageBox(_T("请输入合法的端口:1-65535"));
        goto _End;
    }
    AfxMessageBox(_T("端口合法"));


    //将IP转换
    char AddrIp[16] = { 0 }; //窄字节
    USES_CONVERSION;
    strcpy_s(AddrIp, 16, T2A(ServeIp)); // T2A:宏,进行字符串的转换

    //将服务器的信息放入通用套接字中
    sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(SPort);
    server.sin_addr.s_addr = inet_addr("192.168.73.1");

    //客户端连接服务端
    //将server传给connect
    if ( SOCKET_ERROR == connect(pChatClient->ConnectSock, (struct sockaddr*)&server, sizeof(struct sockaddrr*)) ) {
    /*  char ErrorInfo[256] = { 0 }; //创建数组存储错误信息   
        sprintf_s(ErrorInfo, "Creat Faile : %d", GetLastError());   //把错误信息写入数组       
        AfxMessageBox((CString)ErrorInfo);
    */  
        AfxMessageBox(_T("连接失败!"));
        goto _End;
    }

    pChatClient->MsgShow(_T("服务器连接成功!"));
    while (TRUE) {
        if (SOCKERT_Select(pChatClient->ConnectSock,100,TRUE)) {
            char szBuf[MAX_BUF_SIZE] = { '0' };  //缓冲区
            int iRet = recv(pChatClient->ConnectSock, szBuf, MAX_BUF_SIZE, 0);
                //recv()用来接收远程主机通过套接字sockfd发送来的数据,
                //并把这些数据保存到数组buf中
            if (iRet > 0) {
                pChatClient->MsgShow((CString)szBuf);
            }
            else {
                pChatClient->MsgShow(_T("连接异常,请重新连接!"));
                break;
            }
        }
        Sleep(100);
    }

_End:
    closesocket(pChatClient->ConnectSock);
    return TRUE;

}

服务端


SOCKET ComSock; //用于发送消息

//查看客户端是否发来消息,并快速返回
BOOL SOCKERT_Select(SOCKET Socket, int TimeOut, BOOL bRead) {
    fd_set fdset; //通知执行了select()的进程哪一socket或文件发生了可读或可写事件
                    //long类型的数组,每一个数组元素都能与一打开的文件句柄建立联系
    timeval tv; //判断是否超时,用于select()函数
    FD_ZERO(&fdset);  //清空集合中所有的元素
    FD_SET(Socket, &fdset); //设置hSocket,使集合包含hSocket,即建立联系
    TimeOut = TimeOut > 1000 ? 1000 : TimeOut;
    tv.tv_sec = 0; //秒数
    tv.tv_usec = TimeOut; //微秒数

    int iRet = 0;
    if (bRead) {
        //select()测试指定的fd可读?可写?有异常条件待处理?  //即对socket操作
        iRet = select(0, &fdset, NULL, NULL, &tv);
    }                     //读
    else {

        iRet = select(0, NULL, &fdset, NULL, &tv);
    }                           //写

    if (iRet <= 0) { //返回错误时
        return FALSE;
    }
    else if (FD_ISSET(Socket, &fdset)) {//返回处于就绪状态并且已经包含在fd_set结构中的描述字总数

        return TRUE;
    }
    return FALSE; //返回零时(超时返回零)
}


//通过线程来开启服务器,因为accept是阻塞的
//线程函数
DWORD WINAPI LisenThreadFunc(LPVOID pParam) {
                        //LPVOID :32位的无类型的指针,在使用的时候再强制转换成需要的类型
    CMFCApplication1View *pChatClient = (CMFCApplication1View*)pParam; //强制转换
    ASSERT(pChatClient != NULL); //保证指针不为空  //断言函数,表达式为假则退出程序,为真继续执行

    //用socket函数创建一个socket,用于监听
    //成功则返回一个socket
    pChatClient->ListenSock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

    if (pChatClient->ListenSock == INVALID_SOCKET) {
        AfxMessageBox(_T("创建socket失败!"));
        return 0;
    }

    //绑定,将 ListenSock 绑定在本地的一个ip和端口上
    //1、动态获取用户输入的端口
    int Port = pChatClient->GetDlgItemInt(IDC_LISTENPORT_INPUT);
    if (Port <= 0 || Port > 65535) {
        AfxMessageBox(_T("请输入合适的端口:1-65535"));
        goto _End;
    }

    //2、建立通用套接字
    sockaddr_in service; //一种通用的套接字地址。用来建立所需信息,最后使用类型转换
                         //一般用于bind、connect、recvfrom、sendto等函数的参数
    service.sin_family = AF_INET; //协议族
    service.sin_addr.s_addr = inet_addr("127.0.0.1"); //获取本机所有可能得到的ip地址
    service.sin_port = htons(Port); //传递端口 //htons:将主机字节顺序转换为网络字节顺序

    //3、利用bind进行绑定
    if (bind(pChatClient->ListenSock, (sockaddr*)&service, sizeof(sockaddr_in)) == SOCKET_ERROR) {
        AfxMessageBox(_T("绑定失败!"));
        goto _End;
    }

    AfxMessageBox(_T("绑定成功!"));
    //监听
    if (listen(pChatClient->ListenSock, 4) == SOCKET_ERROR) {
        AfxMessageBox(_T("监听失败!"));
        goto _End;
    }


    //服务器已搭建完毕,开始进行消息监测
    while (TRUE) {
        if (SOCKERT_Select(pChatClient->ListenSock, 1000, TRUE)) {//若有消息
            sockaddr_in ClientSocket;
            int len = sizeof(sockaddr_in);
                                //返回客户端(即对方)的IP地址和端口
            SOCKET ComSock = accept(pChatClient->ListenSock, (struct sockaddr*)&ClientSocket, &len);

            if (ComSock == INVALID_SOCKET) { //若没有收到信息
                continue;
            }

            //当要进行信息交互时,再建一个新线程来进行信息交互
        //  CMFCApplication1View *ClientCopy;

            HANDLE iTtem;
            iTtem = CreateThread(NULL, 0, ClientThreadProc, pChatClient, CREATE_SUSPENDED, NULL);
            pChatClient->comThread = iTtem;
            ResumeThread(iTtem);  //恢复线程的执行

        }
    Sleep(100);
    }

_End:
    closesocket(pChatClient->ListenSock); //强制关闭socket
    return TRUE;
}

由于最近刚学socket,实在不知道怎么改了,请各位大神帮我康康,谢谢大家!(呜呜呜我是新手么的c币)

  • 点赞
  • 回答
  • 收藏
  • 复制链接分享

1条回答