VC6.0创建基于UDP协议的网络聊天程序
只有一个工程UDP,服务器和客户端都是这个工程,因为UDP中C/S区分不强化
只讲关键部分,避免累赘
1.为对话框添加控件
2.为控件绑定变量和消息函数
启动按钮消息函数为Onstart()
发送按钮为OnSendInfo()
3.写一个线程函数用于接收消息(不是成员函数,注意!,在CUDPDlg.cpp文件中定义)如下:
UINT ThreadProcRecv(LPVOID pParam)
{
CUDPDlg * dlg=(CUDPDlg*)pParam;
{
CUDPDlg * dlg=(CUDPDlg*)pParam;
WORD wVertionRequested;
WSADATA wsadata;
int err;
wVertionRequested = MAKEWORD(2,2);
err=WSAStartup(wVertionRequested,&wsadata);
if(err!=0)
{
dlg->MessageBox("加载版本2.2失败!");
return 0;
}
if(LOBYTE(wsadata.wVersion)!=2||HIBYTE(wsadata.wHighVersion)!=2)
{
dlg->MessageBox("加载版本不是套接字2.2版本!");
WSACleanup();
return 0;
}
WSADATA wsadata;
int err;
wVertionRequested = MAKEWORD(2,2);
err=WSAStartup(wVertionRequested,&wsadata);
if(err!=0)
{
dlg->MessageBox("加载版本2.2失败!");
return 0;
}
if(LOBYTE(wsadata.wVersion)!=2||HIBYTE(wsadata.wHighVersion)!=2)
{
dlg->MessageBox("加载版本不是套接字2.2版本!");
WSACleanup();
return 0;
}
SOCKET socketServer=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addr;
SOCKADDR_IN addr;
addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);
addr.sin_family=AF_INET;
addr.sin_port=htons(dlg->m_recvport);
addr.sin_family=AF_INET;
addr.sin_port=htons(dlg->m_recvport);
bind(socketServer,(SOCKADDR *)&addr,sizeof(SOCKADDR));
SOCKADDR_IN addrClient;
int len=sizeof(SOCKADDR);
char buffer[100];
while(TRUE)
{
recvfrom(socketServer,buffer,100,0,(SOCKADDR *)&addrClient,&len);
int len=sizeof(SOCKADDR);
char buffer[100];
while(TRUE)
{
recvfrom(socketServer,buffer,100,0,(SOCKADDR *)&addrClient,&len);
CString info;
info.Format("%s%s","他说:",buffer);
dlg->m_listbox.AddString(info);
dlg->SetHScroll();
dlg->GetDlgItem(IDC_LIST1)->PostMessage(WM_VSCROLL,SB_BOTTOM,0);
}
info.Format("%s%s","他说:",buffer);
dlg->m_listbox.AddString(info);
dlg->SetHScroll();
dlg->GetDlgItem(IDC_LIST1)->PostMessage(WM_VSCROLL,SB_BOTTOM,0);
}
closesocket(socketServer);
WSACleanup();
return 0;
}
WSACleanup();
return 0;
}
4.编写消息函数
void CUDPDlg::OnStart()
{
UpdateData(TRUE);
{
UpdateData(TRUE);
GetDlgItem(IDC_EDIT4)->EnableWindow(FALSE);
GetDlgItem(IDC_BUTTON1)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT1)->EnableWindow(FALSE);
GetDlgItem(IDC_EDIT2)->EnableWindow(FALSE);
if(AfxBeginThread(ThreadProcRecv,this))
MessageBox("启动成功!");
}
void CUDPDlg::OnSendInfo()
{
GetDlgItem(IDC_EDIT3)->SetFocus();
{
GetDlgItem(IDC_EDIT3)->SetFocus();
UpdateData(TRUE);
if(m_sendinfo.IsEmpty())
{
MessageBox("消息为空");
return;
}
WORD wVertionRequested;
WSADATA wsadata;
int err;
wVertionRequested = MAKEWORD(2,2);
err=WSAStartup(wVertionRequested,&wsadata);
if(err!=0)
{
MessageBox("加载套接字2.2版本失败!");
return;
}
if(LOBYTE(wsadata.wVersion)!=2||HIBYTE(wsadata.wHighVersion)!=2)
{
MessageBox("加载版本不是套接字2.2版本!");
WSACleanup();
return;
}
if(m_sendinfo.IsEmpty())
{
MessageBox("消息为空");
return;
}
WORD wVertionRequested;
WSADATA wsadata;
int err;
wVertionRequested = MAKEWORD(2,2);
err=WSAStartup(wVertionRequested,&wsadata);
if(err!=0)
{
MessageBox("加载套接字2.2版本失败!");
return;
}
if(LOBYTE(wsadata.wVersion)!=2||HIBYTE(wsadata.wHighVersion)!=2)
{
MessageBox("加载版本不是套接字2.2版本!");
WSACleanup();
return;
}
SOCKET socketServer=socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addr;
SOCKADDR_IN addr;
addr.sin_addr.S_un.S_addr=inet_addr(m_ip.GetBuffer(0));
addr.sin_family=AF_INET;
addr.sin_port=htons(m_sendport);
char * send;
send=m_sendinfo.GetBuffer(m_sendinfo.GetLength());
send=m_sendinfo.GetBuffer(m_sendinfo.GetLength());
CString text;
text.Format("%s%s","我说:",send);
m_listbox.AddString(text);
SetHScroll();
text.Format("%s%s","我说:",send);
m_listbox.AddString(text);
SetHScroll();
sendto(socketServer,send,m_sendinfo.GetLength()+1,0,(SOCKADDR *)&addr,sizeof(SOCKADDR));
closesocket(socketServer);
WSACleanup();
WSACleanup();
m_sendinfo="";
UpdateData(FALSE);
GetDlgItem(IDC_LIST1)->PostMessage(WM_VSCROLL,SB_BOTTOM,0);
UpdateData(FALSE);
GetDlgItem(IDC_LIST1)->PostMessage(WM_VSCROLL,SB_BOTTOM,0);
}
5.至此已基本完成,运行实例:
1.打开一个客户端(端口号相同)
2.打开一个客户端(端口号不同)
3.打开2个客户端(一台机子)
遗漏点补充:
1.为了方便,可以勾选发送按钮属性框中的默认按钮选项,可以通过enter发送消息
2.列表框控件无法设置水平滚动条,必须自己添加函数
添加函数前先把列表框属性水平滚动条勾选上
然后添加下面成员函数
void CUDPDlg::SetHScroll()
{
CDC* dc = GetDC();
SIZE s;
int index;
CString str;
long temp;
for(index= 0; index< m_listbox.GetCount(); index++)
{
m_listbox.GetText(index,str);
s = dc->GetTextExtent(str,str.GetLength()+1); // 获取字符串的像素大小
// 如果新的字符串宽度大于先前的水平滚动条宽度,则重新设置滚动条宽度
// IDC_LISTBOX为m_List的资源ID
temp = (long)SendDlgItemMessage(IDC_LIST1, LB_GETHORIZONTALEXTENT, 0, 0); //temp得到滚动条的宽度
if (s.cx > temp)
{
SendDlgItemMessage(IDC_LIST1, LB_SETHORIZONTALEXTENT, (WPARAM)s.cx, 0);
}
}
ReleaseDC(dc);
}
void CUDPDlg::SetHScroll()
{
CDC* dc = GetDC();
SIZE s;
int index;
CString str;
long temp;
for(index= 0; index< m_listbox.GetCount(); index++)
{
m_listbox.GetText(index,str);
s = dc->GetTextExtent(str,str.GetLength()+1); // 获取字符串的像素大小
// 如果新的字符串宽度大于先前的水平滚动条宽度,则重新设置滚动条宽度
// IDC_LISTBOX为m_List的资源ID
temp = (long)SendDlgItemMessage(IDC_LIST1, LB_GETHORIZONTALEXTENT, 0, 0); //temp得到滚动条的宽度
if (s.cx > temp)
{
SendDlgItemMessage(IDC_LIST1, LB_SETHORIZONTALEXTENT, (WPARAM)s.cx, 0);
}
}
ReleaseDC(dc);
}
以后每当使用向列表框添加语句时,在后面调用该函数即可
3.UpdateData(TRUE)和UpdateData(FALSE)非常重要,不可缺少,不懂请百度
基本就这样了,希望对你们有所帮助!
工程文件百度网盘下载:https://pan.baidu.com/s/1d1SlR3gJzZA4XEGJmquJLw 提取码:nu77