C语言干UDP聊天程序实现总结1和2.doc_第1页
C语言干UDP聊天程序实现总结1和2.doc_第2页
C语言干UDP聊天程序实现总结1和2.doc_第3页
C语言干UDP聊天程序实现总结1和2.doc_第4页
C语言干UDP聊天程序实现总结1和2.doc_第5页
已阅读5页,还剩7页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

C语言干UDP聊天程序实现总结(一)首先网络编程一般都是基于TCP或UDP的。一般聊天室的程序都是基于UDP的面向连接的。一般的过程都是于下:TCP编程的服务器端一般步骤是:1、创建一个socket,用函数socket();2、绑定IP地址、端口等信息到socket上,用函数bind();3、开启监听,用函数listen();4、接收客户端上来的连接,用函数accept();5、收发数据,用函数send()和recv(),或者read()和write();6、关闭网络连接;7、关闭监听;TCP编程的客户端一般步骤是:1、创建一个socket,用函数socket();2、设置要连接的对方的IP地址和端口等属性;3、连接服务器,用函数connect();4、收发数据,用函数send()和recv(),或者read()和write();5、关闭网络连接; 与之对应的UDP编程步骤要简单许多,分别如下:UDP编程的服务器端一般步骤是:1、创建一个socket,用函数socket();2、绑定IP地址、端口等信息到socket上,用函数bind();3、循环接收数据,用函数recvfrom();4、关闭网络连接; UDP编程的客户端一般步骤是:1、创建一个socket,用函数socket();2、设置对方的IP地址和端口等属性;3、发送数据,用函数sendto();4、关闭网络连接; 关于更详细的网络编程方面的大家可以找相关的书籍来看。这里我只是简单的介绍。可能还不准确。呵呵。初学者嘛!一步步学好啊。这里我写的就是基于UDP的。由于是win32的程序。首先要把软件模型编辑出来。这里就不多说了。一般学了的都会。用一个对话框来实现的。主要有一个大的编辑框为接收框。一个稍大的在下面作为发送编辑框。两个小的编辑框用来记录对方的IP和自己的用户名。当然还有一个发送按钮。 关于图我在学生作品里面有。也有代码。好了,现在就来编辑代码了。在编辑代码前我们需要的库是ws2_32.lib和头文件winsock2.h.一定要记得加进去哦。否则就会报错。首先我们做初始化套接字功能。先申明一个全局的WSADATA wsdata;的加载ws2_32.lib套接库的变量。在对话框的InitDialog部分加入:WSAStartup(MAKEWORD(2,2),&wsadata);WSAStartup是启动ws2_32.lib库的函数。MAKEWORD是把两个高位的和地位的数和成一个DWORD类型的数。前一个参数是低字节。后面的是高字节。当然这里你还可以判断加载是否成功。然后在全局的申明一个SOCKET m_socket 的套接字变量。编写一个函数用来初始化套接字和绑定套接字。BOOL InitSockt(HWND hwnd) /初始化套接字。socket参数第一个是网络套接字族。一般都是AF_INET,第二个参数是套接字类型。TCP的是SOCK_STREAM /而UDP的是SOCK_DGRAM的形式。第三个是初始化的协议。一般都是0. m_socket = socket(AF_INET,SOCK_DGRAM,0); if(INVALID_SOCKET = m_socket)/初始化失败将返回INVALID_SOCKET. MessageBox(hwnd,TEXT(创建套接字失败!),TEXT(失败),MB_OK); WSACleanup(); return FALSE; /初始化地址。 SOCKADDR_IN addr; addr.sin_addr.S_un.S_addr =htonl(INADDR_ANY);/地址是一个结构体。用htonl把它转化为网络字节序。 addr.sin_family = AF_INET;/地址家族。 addr.sin_port = htons(port);/端口。这个port是自己申明的变量,一般自己申明的端口号要大于1024.同样用htons转化网络形式。 int retbind; /绑定套接字。 retbind = bind(m_socket,(SOCKADDR*)&addr,sizeof(addr); if(SOCKET_ERROR = retbind) MessageBox(hwnd,TEXT(绑定套接字失败,无法启动网络n检查网络在后再登陆!), TEXT(网络失败),MB_OK | MB_ICONSTOP); SetWindowText(GetDlgItem(hwnd,IDC_STC),TEXT(绑定套接字失败!);/在静态控件中显示。 closesocket(m_socket);/如果绑定没有成功记得关闭套接字。 return FALSE; SetWindowText(GetDlgItem(hwnd,IDC_STC),TEXT(绑定套接字成功!); /同样成功,在静态控件中显示出来。 return TRUE;这个函数作为服务端的初始化。也将放在InitDialog里面来调用。由于这个程序是在一个对话框中实现客户端和服务端的。所以我们要用到多线程的知识。我们要创建一个线程来接收来自服务端和客户端的数据。我们还是一样在初始化对话框中来创建线程。 HANDLE handle;/线程句柄。 LPINFO *lpinfo; lpinfo-Hwnd=hwnd; lpinfo-server=m_socket; /创建接收端线程, 将句柄和socket作为结构体变量传入线程函数中。 handle = CreateThread(NULL,0,ThreadFunc,(LPVOID)lpinfo,0,NULL); CloseHandle(handle);/记得关闭线程。 创建线程函数原型:HANDLE CreateThread( LPSECURITY_ATTRIBUTES lpThreadAttributes, SIZE_T dwStackSize, LPTHREAD_START_ROUTINE lpStartAddress, LPVOID lpParameter, DWORD dwCreationFlags, LPDWORD lpThreadId); 因为我们的线程函数将用到窗口的句柄和我们刚初始化的套接字作为一个结构的参数传入线程函数中。DWORD WINAPI ThreadFunc(LPVOID lp)线程函数只能这么调用。它只有一个LPVOID的无类型的指针。我们就通过它来传递我们需要的数据。因为他是无类型指针。所以我们传入的时候也采用LPVOID强制转换一下。关于CreateThread函数这里就不多讲了。有兴趣可以看看多线程方面的东西就可以了,可以查看MSDN,要注意的是倒数第二个参数是创建后是否立即执行。为0就立即执行。其实我们刚开始就将m_sock变量作为全局的变量,这里可以不用作为参数传入进去了 。但是我是初学者。要懂得有这样的方式来传递数据。以后就是不能有全局数据也能一通百通的用了啊。呵呵。既然创建了线程 。我们就来处理线程函数吧。为了达到有QQ一样的有用户名和时间,我这里也调用了时间的函数和声音函数。还要注意的是怎么样在编辑框里面让它自动的换行。当然你首先在资源编辑里面属性里面就的让它有换行的功能。然后采用字符串后面加rn的方式使它每次需要换行的时候自动换行,这样就实现了QQ的方式。函数如下:DWORD WINAPI ThreadFunc(LPVOID lp) /这是上面讲的用结构体传入的参数,因为我们传入的时候是将它强制转换为无类型的。在这里我们又的把它强制转换回来。 /注意要强制转换的数据类型。 SOCKET server=(LPINFO*)lp)-server; HWND hwnd = (LPINFO*)lp)-Hwnd; /同样由于我们这里是接收数据的,我们就的再申明一个接收端的地址变量。以便于接收端用户能用到。 SOCKADDR_IN addrfrom;/定义接收端地址信息。 int len = sizeof(SOCKADDR); TCHAR recvBuf256; TCHAR tempBuf512; TCHAR BuffLARGE; TCHAR cUseName50; TCHAR cResult50; SYSTEMTIME time;/时间结构体变量。 int retval; /我们这里采用无限循环来使它接收数据直到对方关闭。 while(TRUE) /因为我们是用UDP的方式。所以我们这里用recvform来接收数据。若是TCP则采用recv。 /recvform的参数。第一是套接字,第二个是你要接收的字符缓冲区。第三个是缓冲区大小。第四个是标记我们设为0就好。 /第五个参数是接收对方地址。第六个是地址长度。 / 函数原型:int recvfrom( SOCKET s, char* buf,int len, int flags,struct sockaddr* from,int* fromlen); retval = recvfrom(server,recvBuf,sizeof(recvBuf),0, (SOCKADDR*)&addrfrom,&len); if(SOCKET_ERROR = retval) break;/不成功我们将退出。 SetWindowText(GetDlgItem(hwnd,IDC_STC),TEXT(聊天连接成功!); /因为我们PlapSound函数需要窗口实例句柄。我们采用GetWindowLong来的到它。 HINSTANCE appInstance = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE);/调用实例句柄 /消息受到声音. 关于这个函数这里不多将了。查看MSDN. PlaySound(TEXT(IDA_MYMUSIC),appInstance,SND_RESOURCE|SND_ASYNC); GetLocalTime(&time);/调用电脑的时间。 WORD wSecond=time.wSecond; wsprintf(cResult,TEXT(%02u-%02u-%02u), time.wHour,time.wMinute,time.wSecond); /将时间格式化后存入缓冲区。这里我还要说明一点。有两个函数这里可以实现。 /wsprintf和sprintf。但是他们有区别的。主要是能放的缓冲区大小问题。大家可以去试试他们的区别。 GetDlgItemText(hwnd,IDC_EDT_USE,cUseName,sizeof(cUseName); sprintf(tempBuf,【%s 】t %s,cUseName,cResult); strcat(tempBuf,rn);/实现自动换行。 strcat(tempBuf,recvBuf); strcat(tempBuf,rn);/实现自动换行。 GetDlgItemText(hwnd,IDC_EDT_RECV,Buff,sizeof(Buff); strcat(Buff,tempBuf); /做好了所以工作后将他们集体输出到编辑框中。原理是先得到编辑框的内容。在加要输出的内容。后一起输出到编辑框。 SetDlgItemText(hwnd,IDC_EDT_RECV,Buff); return 0;注意我们用到声音的函数。要加入Winmm.lib库哦。否则就会报错!还有个头文件。Mmsystem.h。这个可加也可不加。有windows.h就可以了。好啦!我们接收端的线程就完工了。程序完成一半了。先休息一下。呵呵。注:可以结合我在学生作品中的代码。虽然代码不怎么样!呵呵。C语言干UDP聊天程序实现总结(二)好了。上一节讲套接字的初始化和接收端线程的编写。这一节我们来写发送端。发送端的主要功能是将发送编辑器里面的数据发送过去。我们用一个函数来实现。void SendData(HWND hwnd)函数首先还是创建一个网络地址。初始化后。得到姓名编辑框的名字和IP编辑框的IP;然后将数据和 姓名发送给接收端线程。函数实现如下:void SendData(HWND hwnd)TCHAR cResult50;TCHAR sendBuf256;/作为单次传输不的超过256. 也就是1K.若要大于它就要分割数据。采writefile和readfile来实现。TCHAR cResultU50;TCHAR cResultI50;/ 这里我们先得到IP编辑框里面的内容。GetDlgItemText(hwnd,IDC_EDT_ADDR,cResult,sizeof(cResult);/初始化发送端的网络地址结构。还是跟前面一样。/但是我们前面的地址由于是服务端可以接收多人的数据。所以我们用INSOCK_ANY来初始化。/但是这里我们要先得到对方IP.再赋给网络地址结构。SOCKADDR_IN addrTo;/在这里我开始没有用(char*)来转换得不到IP,后来我用MessageBox在它的前面输出后居然可以了。所以我在下面加上(char*)/就成功了。所以我们经常可以采用MessageBox来看结果。addrTo.sin_addr.S_un.S_addr = inet_addr(char*)cResult);/记得强制转化为char* addrTo.sin_family = AF_INET;addrTo.sin_port = htons(port); /下面是判断用户是否输入了名字和IP. GetDlgItemText(hwnd,IDC_EDT_USE,cResultU,sizeof(cResultU); GetDlgItemText(hwnd,IDC_EDT_ADDR,cResultI,sizeof(cResultI);if(0 = strcmp(cResultU,) MessageBox(hwnd,TEXT(请登陆用户名和IP!),TEXT(错误!),MB_OK); return ;if(0 = strcmp(cResultI,) MessageBox(hwnd,TEXT(请登陆用户名和IP!),TEXT(错误!),MB_OK); return ;/得到发送编辑框里面的数据。GetDlgItemText(hwnd,IDC_EDT_SEND,sendBuf,sizeof(sendBuf);if(strcmp(sendBuf,) = 0) MessageBox(hwnd,TEXT(不能发送看空信息!),TEXT(错误),MB_OK); return ; int retsend;/这里UDP的我们采用sendto来发送数据。TCP的采用send。参数跟recvfrom一样。可以对照来学习。retsend = sendto(m_socket,sendBuf,sizeof(sendBuf),0, (SOCKADDR*)&addrTo,sizeof(addrTo); if(retsend = 0) MessageBox(hwnd,TEXT(发送失败!),TEXT(失败),MB_OK); SetDlgItemText(hwnd,IDC_EDT_SEND,);/最后清空发送编辑框。 完工!发送端的函数就这么简单。最基本的聊天程序原理都完了。后面的就是自己怎么去加一些自己喜欢的东西啦。像我写的。用户名和IP必须在另一个对话框中来填写。是不允许在主对话框中直接的写。所以这就涉及到创建子对话框的内容了。在这里我只是简单的说说。因为主要还是讲网络编程的啦。首先创建对话框我们有两个函数可以实现。1.对话框模板资源创建一个无模式的对话框 HWND CreateDialog(HINSTANCE hlnstance,LPCTSTR lpTemplate,HWND hWndParent,DLGPROC IpDialogFunc);2. 根据对话框模板资源创建一个模态的对话框:int DialogBox(HINSTANCE hlnstance,LPCTSTRIpTemplate,HWND hWndParent,DLGPROC IpDialogFunc);关于模式和无模式的观念。这里就不讲了。大家可以参考其他书籍。其实你看两个函数创建的参数都一样。我这里采用的是模式对话框。 / 调用应用程序实例句柄。这个函数前面已经用过。 HINSTANCE appInstance = (HINSTANCE)GetWindowLong(hwnd,GWL_HINSTANCE); /创建子对话框, DialogBox(appInstance,MAKEINTRESOURCE(IDD_ABOUT),hwnd,(DLGPROC)DialogProc); 第一个是实例的句柄。第二个是资源,我们采用MAKEINTRESOURCE来加载。第三个你要创建子窗口的父窗口的句柄。当然如果你没有父窗口的话。直接NULL就可以了。最后一个参数是回调函数。也就是程序处理函数。大多是处理消息的。其实他跟你开始建立的窗口处理函数是一样的。也没什么好讲的。BOOL CALLBACK DialogProc(HWND hwndDlg,UINT UMsg,WPARAM wParam,LPARAM IParam)TCHAR cResultU50;TCHAR cResultI50;switch(UMsg) case WM_INITDIALOG: BOOL IsChecked = SendMessage(GetDlgItem(hwndDlg,IDC_CHK),BM_GETCHECK,0,0); if(IsChecked) SetWindowText(GetDlgItem(hwndDlg,IDC_EDT1),TEXT(流浪的心); SetWindowText(GetDlgItem(hwndDlg,IDC_EDT2),TEXT(127.0.0.1); EnableWindow(GetDlgItem(hwndDlg,IDC_EDT1),FALSE); EnableWindow(GetDlgItem(hwndDlg,IDC_EDT2),FALSE); break; case WM_COMMAND: /鼠标点击消息。 int id = wParam; switch(id) case IDC_CHK: BOOL IsChecked = SendMessage(GetDlgItem(hwndDlg,IDC_CHK),BM_GETCHECK,0,0); if(IsChecked) SetWindowText(GetDlgItem(hwndDlg,IDC_EDT1),TEXT(侯永华); SetWindowText(GetDlgItem(hwndDlg,IDC_EDT2),TEXT(127.0.0.1); EnableWindow(GetDlgItem(hwndDlg,IDC_EDT1),FALSE); EnableWindow(GetDlgItem(hwndDlg,IDC_EDT2),FALSE); else EnableWindow(GetDlgItem(hwndDlg,IDC_EDT1),TRUE); EnableWindow(GetDlgItem(hwndDlg,IDC_EDT2),TRUE); SetWindowText(GetDlgItem(hwndDlg,IDC_EDT1),TEXT(); SetWindowText(GetDlgItem(hwndDlg,IDC_EDT2),TEXT(); break; case IDC_BTNOK: GetDlgItemText(hwndD

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论