weixin_36079422 2017-04-11 08:31 采纳率: 50%
浏览 1857
已结题

MFC TCP聊天程序,客户端为什么接受不到服务器发送的信息

客户端://连接服务器端
void CChat_TCPClientDlg::OnButtonConnnet()
{
m_socket = socket(AF_INET,SOCK_STREAM,0);
int retconnect;
unsigned short temport;
UpdateData(TRUE);//刷新控件的值到变量上,刷新端口号
temport = (unsigned short)m_ClientPort;
DWORD dwIP;
((CIPAddressCtrl*)GetDlgItem(IDC_IPADDRESS))->GetAddress(dwIP);

sockaddr_in addrTo;
addrTo.sin_addr.S_un.S_addr = htonl(dwIP);
addrTo.sin_family = AF_INET;
addrTo.sin_port = htons(temport);

retconnect = connect(m_socket,(sockaddr*)&addrTo,sizeof(sockaddr));
if(SOCKET_ERROR == retconnect)
{
    SetDlgItemText(IDC_EDIT_STATE,"连接失败");
    return;
}
else
    SetDlgItemText(IDC_EDIT_STATE,"连接成功");

CButton *pButton=(CButton*)GetDlgItem(IDC_BUTTON_CONNNET);
pButton->EnableWindow(FALSE);
pButton=(CButton*)GetDlgItem(IDC_BUTTON_OUT);
pButton->EnableWindow(TRUE);
pButton=(CButton*)GetDlgItem(IDC_BUTTON_SEND);
pButton->EnableWindow(TRUE);
pButton=(CButton*)GetDlgItem(IDC_BUTTON_CLEAR);
pButton->EnableWindow(TRUE);


GetDlgItemText(IDC_EDIT_USERNAME,username);
char NewMember[200];
CTime tm=CTime::GetCurrentTime();
CString str=tm.Format("%Y-%m-%d %H:%M:%S");
sprintf(NewMember,"%s--->进入聊天室 %s",username,str);
send(m_socket,NewMember,sizeof(NewMember),0);


HANDLE thread;
thread=CreateThread(NULL,0,RecvProc,NULL,0,NULL);
CloseHandle(thread);

}

DWORD WINAPI CChat_TCPClientDlg::RecvProc(LPVOID lpParameter)
{
CChat_TCPClientDlg* pDlg = (CChat_TCPClientDlg*)(::AfxGetApp()->GetMainWnd());
SOCKET ClientSocket;
ClientSocket = pDlg->m_socket;
HWND hwnd = pDlg->m_hWnd;
int retrecv=0;
char recvbuf[1024];
while(1)
{
memset(recvbuf,0,sizeof(recvbuf));
retrecv = recv(ClientSocket,recvbuf,1024,0);
if(SOCKET_ERROR == retrecv)
{
::SetDlgItemText(hwnd,IDC_EDIT_STATE,"连接断开");
break;
}
else
{
pDlg->m_ListRecv.AddString(recvbuf);
pDlg->m_ListRecv.SetHorizontalExtent(10000);

    }
}
return 0;

}

void CChat_TCPClientDlg::OnButtonSend()
{
// TODO: Add your control notification handler code here
CString tempSend;
char strSend[300];
GetDlgItemText(IDC_EDIT_SEND,tempSend);
GetDlgItemText(IDC_EDIT_USERNAME,username);
sprintf(strSend,"%s说: %s",username,tempSend);
int retsend;
retsend = send(m_socket,strSend,strlen(strSend)+1,0);
if(retsend==SOCKET_ERROR)
{
CButton pButton=(CButton)GetDlgItem(IDC_BUTTON_OUT);
pButton->EnableWindow(FALSE);
pButton=(CButton*)GetDlgItem(IDC_BUTTON_SEND);
pButton->EnableWindow(FALSE);
pButton=(CButton*)GetDlgItem(IDC_BUTTON_CLEAR);
pButton->EnableWindow(FALSE);
pButton=(CButton*)GetDlgItem(IDC_BUTTON_CONNNET);
pButton->EnableWindow(TRUE);
SetDlgItemText(IDC_EDIT_STATE,"连接断开");
}
else
{
SetDlgItemText(IDC_EDIT_SEND,"");
}
}

void CChat_TCPClientDlg::OnButtonOut()
{
// TODO: Add your control notification handler code here
/* GetDlgItemText(IDC_EDIT_USERNAME,username);
char leavechar[50];
sprintf(leavechar,"%s<---离开聊天室",username);
send(m_socket,leavechar,sizeof(leavechar),0);*/

closesocket(m_socket);
SetDlgItemText(IDC_EDIT_STATE,"没有连接");
CButton *pButton=(CButton*)GetDlgItem(IDC_BUTTON_CONNNET);
pButton->EnableWindow(TRUE);
pButton=(CButton*)GetDlgItem(IDC_BUTTON_OUT);
pButton->EnableWindow(FALSE);
pButton=(CButton*)GetDlgItem(IDC_BUTTON_SEND);
pButton->EnableWindow(FALSE);
pButton=(CButton*)GetDlgItem(IDC_BUTTON_CLEAR);
pButton->EnableWindow(FALSE);

}

void CChat_TCPClientDlg::OnButtonClear()
{
// TODO: Add your control notification handler code here
m_ListRecv.ResetContent();
}
服务器:
// the minimized window.
HCURSOR CChat_TCPSrvDlg::OnQueryDragIcon()
{
return (HCURSOR) m_hIcon;
}

BOOL CChat_TCPSrvDlg::InitSocket(unsigned short port)
{
//初始化连接套接字
ClientTotal = 0;
for(int i=0;i<20;i++)
{

ClientSocket[i] = 0;
ClientAddr[i] = "";
}

//创建绑定监听套接字
m_socket = socket(AF_INET,SOCK_STREAM,0);
if(INVALID_SOCKET==m_socket)
{
    SysStr = "创建socket失败";
    m_SysMsg.AddString(SysStr);
    return FALSE;
}
else
{
    SysStr = "创建socket成功";
    m_SysMsg.AddString(SysStr);
    m_SysMsg.SetHorizontalExtent(1000);
}

//地址族赋值
sockaddr_in addrsock;
addrsock.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrsock.sin_family = AF_INET;
addrsock.sin_port = htons(port);

//绑定套接字
int retbind;
retbind = bind(m_socket,(SOCKADDR*)&addrsock,sizeof(SOCKADDR));
if(SOCKET_ERROR==retbind)
{
    closesocket(m_socket);

    SysStr = "bind 失败";
    m_SysMsg.AddString(SysStr);
    SysStr = "启动失败";
    m_SysMsg.AddString(SysStr);
    return FALSE;
}
else
{
    SysStr = "bind成功";
    m_SysMsg.AddString(SysStr);
}

//设置监听模式
if(listen(m_socket,20)!=0)
{

    SysStr = "启动失败";
    m_SysMsg.AddString(SysStr);
    return FALSE;
}
else
{
    SysStr = "服务器启动成功";
    m_SysMsg.AddString(SysStr);
}

return TRUE;

}

//启动服务器
void CChat_TCPSrvDlg::OnButtonStart()
{
// TODO: Add your control notification handler code here
SrvState = TRUE;
ClientTotal = 0;
unsigned short temport;
BOOL InitSock;
UpdateData(TRUE);
temport = m_Port;
if(temport>=1025 && temport<=9999)
{
InitSock = InitSocket(temport); //调用初始化套接字

    //让“启动按钮”不可用,和让“关闭按钮”可用
    CButton *pButton=(CButton*)GetDlgItem(IDC_BUTTON_CLOSE);
    pButton->EnableWindow();
    pButton=(CButton*)GetDlgItem(IDC_BUTTON_START);
    pButton->EnableWindow(FALSE);

    //创建一级线程,用于监听用户的连接
    HANDLE hThread=CreateThread(NULL,0,AcceptClient,NULL,0,NULL);
    CloseHandle(hThread);
}
else
{
    SysStr="端口号不在使用范围内,启动失败";
    m_SysMsg.AddString(SysStr);
    m_SysMsg.SetHorizontalExtent(1000);
}

hMutex = CreateMutex(NULL,FALSE,NULL);

}

//一级线程,连接客户请求
DWORD WINAPI CChat_TCPSrvDlg::AcceptClient(LPVOID lpParameter)
{
CChat_TCPSrvDlg* pDlg = (CChat_TCPSrvDlg*)(::AfxGetApp()->GetMainWnd());
SOCKET socketacp = pDlg->m_socket;

sockaddr_in addrClient;
int len = sizeof(sockaddr);
while(pDlg->SrvState)
{
    pDlg->ClientSocket[pDlg->ClientTotal]=accept(socketacp,(SOCKADDR *)&addrClient,&len);
    WaitForSingleObject(pDlg->hMutex,INFINITE);
    pDlg->ClientTotal++;
    pDlg->SysStr = "新用户加入";
    pDlg->m_SysMsg.AddString(pDlg->SysStr);
    ReleaseMutex(pDlg->hMutex);
    if(pDlg->ClientTotal==1) //只是用来启动二级进程,当第二个客户端连接上后,if语句不执行,recv进程一直在执行
    {
        //创建二级线程,用于接收数据。
        HANDLE hThread=CreateThread(NULL,0,RecvProc,NULL,0,NULL);
        CloseHandle(hThread);
    }
}

return 0;

}

//二级线程,接收用户消息,并显示
DWORD WINAPI CChat_TCPSrvDlg::RecvProc(LPVOID lpParameter)
{
CChat_TCPSrvDlg* pDlg1 = (CChat_TCPSrvDlg*)(::AfxGetApp()->GetMainWnd());
fd_set fsRead;
timeval tm = {0,10000};
char recvBuf[200];
while(pDlg1->SrvState)
{
FD_ZERO(&fsRead);
for(int m=0;m<(pDlg1->ClientTotal);m++) //对所有用户进行select监视
FD_SET((pDlg1->ClientSocket[m]),&fsRead);
int retRead = select(pDlg1->ClientTotal+1,&fsRead,NULL,NULL,&tm);

    if(SOCKET_ERROR == retRead)
        return 1;
    else
    {
        for(int index=0;index<(pDlg1->ClientTotal);index++)
        {
            if(FD_ISSET(pDlg1->ClientSocket[index],&fsRead))
            {
                memset(recvBuf,0,sizeof(recvBuf));
                recv(pDlg1->ClientSocket[index],recvBuf,sizeof(recvBuf),0);
                if(strlen(recvBuf)==0)          //判断用户是否退出
                {

                    pDlg1->SysStr = "有一个用户离开";
                    pDlg1->m_SysMsg.AddString(pDlg1->SysStr);
                    pDlg1->ClientSocket[index] = pDlg1->ClientSocket[pDlg1->ClientTotal-1]; //将最后一个放到刚刚退出的client那里去
                    pDlg1->ClientSocket[pDlg1->ClientTotal-1] = 0; //保证所有未退出的客户端都在前面
                    if(pDlg1->ClientTotal==0)
                        return 0;
                    pDlg1->ClientTotal--;
                }
                else
                {
                    pDlg1->m_UserMsg.AddString(recvBuf);
                    pDlg1->m_UserMsg.SetHorizontalExtent(10000);
                    for(int n=0;n<(pDlg1->ClientTotal);n++)
                    {
                            send(pDlg1->ClientSocket[n],recvBuf,sizeof(recvBuf),0);
                    }

                }
            }
        }
    }
}

return 0;

}

//关闭服务器
void CChat_TCPSrvDlg::OnButtonClose()
{
// TODO: Add your control notification handler code here
WaitForSingleObject(hMutex,INFINITE);

SysStr="服务器已关闭";
m_SysMsg.AddString(SysStr);
SrvState = FALSE;
for(int k=0;k<ClientTotal;k++)
    send(ClientSocket[k],"服务器已关闭,请断开服务器重新连接",sizeof("服务器已关闭,请断开服务器重新连接")+1,0);
closesocket(m_socket);
while(ClientTotal>0)
{
    closesocket(ClientSocket[ClientTotal-1]);
    ClientTotal--;
}
CButton *pButton=(CButton*)GetDlgItem(IDC_BUTTON_CLOSE);
pButton->EnableWindow(FALSE);
pButton=(CButton*)GetDlgItem(IDC_BUTTON_START);
pButton->EnableWindow();

}

void CChat_TCPSrvDlg::OnClickedButtonSend()
{
// TODO: 在此添加控件通知处理程序代码
CString tempSend;
char strSend[300];
GetDlgItemText(IDC_EDIT_SEND,tempSend);
sprintf(strSend,"服务器: %s",tempSend);
send(m_socket,strSend,strlen(strSend)+1,0);
m_UserMsg.AddString(strSend);
SetDlgItemText(IDC_EDIT_SEND,"");
}

void CChat_TCPSrvDlg::OnClickedButtonClear()
{
// TODO: 在此添加控件通知处理程序代码
m_UserMsg.ResetContent();
}
图片说明

  • 写回答

2条回答 默认 最新

  • ljheee 2017-04-11 08:58
    关注

    SetDlgItemText(IDC_EDIT_STATE,"连接成功");
    这里会提示连接成功吗

    评论

报告相同问题?

悬赏问题

  • ¥15 python:excel数据写入多个对应word文档
  • ¥60 全一数分解素因子和素数循环节位数
  • ¥15 ffmpeg如何安装到虚拟环境
  • ¥188 寻找能做王者评分提取的
  • ¥15 matlab用simulink求解一个二阶微分方程,要求截图
  • ¥30 乘子法解约束最优化问题的matlab代码文件,最好有matlab代码文件
  • ¥15 写论文,需要数据支撑
  • ¥15 identifier of an instance of 类 was altered from xx to xx错误
  • ¥100 反编译微信小游戏求指导
  • ¥15 docker模式webrtc-streamer 无法播放公网rtsp