套接字网络编程.docx_第1页
套接字网络编程.docx_第2页
套接字网络编程.docx_第3页
套接字网络编程.docx_第4页
套接字网络编程.docx_第5页
已阅读5页,还剩14页未读 继续免费阅读

下载本文档

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

文档简介

18.3 | Windows套接字技术套接字(Socket)是网络通信的基本构件,最初是由加利福尼亚大学Berkeley学院为UNIX开发的网络通信编程接口,它只能运行在UNIX操作系统,不支持DOS和Windows操作系统。随着Windows操作系统的日益推广,90年代初,微软和第三方厂商共同制定了一套标准,即Windows Socket规范,简称WinSock。本节将介绍有关Windows套接字的相关技术。18.3.1 套接字概述套接字的概念与文件句柄类似,一个套接字就是一个通信标识,由一个短整数表示,实际上就是一个句柄,代表网络协议中的一组数据,该数据包含了通信双方的IP地址和当前的连接状态等信息。我们知道,如果一个文件被打开,可以通过文件句柄对文件进行读写操作,套接字也一样,只不过套接字提供的函数更多一些。套接字存在于通信区域中,由协议、地址、端口来描述并惟一确定,根据传输协议的不同,套接字可分为3种类型:流式套接字、数据报套接字和原始套接字。流式套接字提供了一个面向连接的、可靠的、数据无错且按顺序接收的服务,这种套接字对应的是面向连接的传输协议,如TCP/IP协议簇中的TCP。数据报套接字提供了一个无连接服务,不提供无错保证,数据可能丢失或重复,且接受顺序混乱,该套接字所对应的是无连接传输协议,如TCP/IP协议簇中的UDP。原始套接字允许直接访问低层的协议,如IP、ICMP协议,该套接字常用于访问服务器中配置的新设备。18.3.2 WinSock API相关函数WinSock提供了许多套接字函数,它们并不代表协议的某一个层次,其实质就是一组编程接口,用户利用这些函数可以很容易地进行编程。(1)socket函数socket函数用于创建一个套接字。语法:SOCKET socket (int af, int type, int protocol );af:标识一个地址家族,通常为AF_INET。type:标识套接字类型,如果为SOCK_STREAM,表示流式套接字;如果为SOCK_DGRAM,表示数据报套接字。protocol:标识一个特殊的协议被用于这个套接字,通常为0,表示采用默认的TCP/IP协议。(2)accpet函数accpet函数用于接受客户端的连接请求。返回值是一个新的套接字,它对应于已经接受的客户端连接,对于该客户端的所有后续操作,都应使用这个新的套接字。语法:SOCKET accept (SOCKET s,struct sockaddr FAR* addr, int FAR* addrlen);s:是一个套接字,它应处于监听状态。addr:是一个sockaddr_in结构指针,包含一组客户端的端口号、IP地址等信息。addrlen:用于接收参数addr的长度。(3)bind函数bind函数用于将套接字绑定到一个已知的地址上。如果函数执行成功,返回值为0,否则为SOCKET_ERROR。语法:int bind (SOCKET s, const struct sockaddr FAR* name, int namelen );s:是一个套接字。name:是一个sockaddr结构指针,该结构中包含了要绑定的地址和端口号。namelen:确定name缓冲区的长度。在定义一个套接字后,需要调用bind函数为其指定本机地址、协议和端口号。例如,创建一个套接字s,将其绑定到3010端口上,其代码如下:int port = 3010;SOCKET s = socket(AF_INET,SOCK_STREAM,IPPROTO_IP);sockaddr_in addr;addr.sin_family = AF_INET;/内部网络协议TCP/UDP等addr.sin_port = htons(port); /端口号addr.sin_addr.s_addr = htonl(INADDR_ANY);if (bind(s,(LPSOCKADDR)&addr,sizeof(addr)=0)MessageBox(成功);(4)closesocket函数closesocket函数用于关闭某个套接字。语法:int closesocket (SOCKET s );s:标识一个套接字。如果参数s设置有SO_DONTLINGER选项,则调用该函数后会立即返回,但此时如果有数据尚未传送完毕,会继续传递数据,然后才关闭套接字。(5)connect函数connect函数用于发送一个连接请求。如果函数执行成功,返回值为0,否则为SOCKET_ERROR。用户可以通过WSAGetLastError得到其错误描述。语法:int connect (SOCKET s,const struct sockaddr FAR* name, int namelen);s:标识一个套接字。name:套接字s想要连接的主机地址和端口号。namelen:name缓冲区的长度。(6)htons函数htons函数将一个16位的无符号短整型数据由主机排列方式转换为网络排列方式。语法:u_short htons (u_short hostshort );hostshort:一个主机排列方式的无符号短整型数据。(7)htonl函数htonl函数将一个32位的无符号长整型数据由主机排列方式转换为网络排列方式。语法:u_long htonl (u_long hostlong );hostlong:一个主机排列方式的无符号长整型数据。(8)inet_addr函数inet_addr函数将一个由字符串表示的地址转换为32位的无符号长整型数据。语法:unsigned long inet_addr (const char FAR * cp );cp:一个表示IP地址的字符串。(9)listen函数listen函数用于将套接字置入监听模式。语法:int listen (SOCKET s, int backlog );s:套接字。backlog:表示等待连接的最大队列长度。例如,如果backlog被设置为3,此时有4个客户端同时发出连接请求,那么前3个客户端连接会放置在等待队列中,第4个客户端会得到错误信息。(10)recv函数recv函数用于从连接的套接字中返回数据。语法:int recv (SOCKET s, char FAR* buf, int len, int flags );recv函数参数的说明如表18.5所示。表18.5 recv函数参数说明参 数 名 称参 数 描 述S标识一个套接字Buf是接收数据的缓冲区Len是buf的长度Flags表示函数的调用方式,可选值如下:MSG_PEEK_用来查看传来的数据,在序列前端的数据会被复制一份到返回缓冲区中,但是这个数据不会从序列中移走MSG_OOB_用来处理Out-Of-Band数据(11)select函数select函数用来检查一个或多个套接字是否处于可读、可写或错误状态。语法:int select (int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout );select函数参数说明如表18.6所示。表18.6 select函数参数说明参 数 名 称参 数 描 述nfds没有实际意义,只是为了和UNIX下的套接字兼容readfds标识一组被检查可读的套接字writefds标识一组被检查可写的套接字exceptfds是被检查有错误的套接字timeout标识函数的等待时间(12)send函数send函数在已经建立连接的套接字上发送数据。语法:int send (SOCKET s, const char FAR * buf, int len, int flags );send函数参数说明如表18.7所示。表18.7 send函数参数说明参 数 名 称参 数 描 述s标识一个套接字buf是存放要发送数据的缓冲区len标识缓冲区长度flags标识函数的调用方式(13)WSAStartup函数WSAStartup函数用于初始化WS2_32动态库。它应该是应用程序第1个调用的Windows Socket函数,用于确定Windows Socket使用的版本。语法:int WSAStartup (WORD wVersionRequested, LPWSADATA lpWSAData );wVersionRequested:标识调用者使用的Windows Socket的版本,高字节记录修订版本,低字节记录主版本。例如,如果Windows Socket的版本为2.1,则高字节记录1,低字节记录2。lpWSAData:记录Windows Socket的详细信息。下面的代码用于确定Windows Socket使用的版本。WSADATA wsd;WSAStartup(MAKEWORD(2,2),&wsd);(14)WSACleanup函数WSACleanup函数与WSAStartup函数是相对的,用于终止使用WS2_32动态库。语法:int WSACleanup (void);说明:当Windows Socket使用完成时,应调用WSACleanup函数释放分配给应用程序或动态库的资源。(15)WSAAsyncSelect函数WSAAsyncSelect函数用于将网络中发生的事件关联到窗口的某个消息中。语法:int WSAAsyncSelect (SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent );WSAAsyncSelect函数参数说明如表18.8所示。表18.8 WSAAsyncSelect函数参数说明参 数 名 称参 数 描 述s标识套接字hWnd标识窗口句柄wMsg标识窗口消息lEvent标识网络中的事件18.3.3 使用套接字函数设计网络聊天室在18.3.2节中笔者介绍了常用的套接字函数,接下来将利用这些套接字函数设计一个网络聊天室程序。程序由两个实例组成,第1个实例为服务器端,负责接收用户的连接请求,并转发用户信息。第2个实例为客户端,负责连接服务器并发送信息。服务器端程序设计步骤如下:ch1806实例位置:mr/18/sl/06(1)创建一个基于对话框的应用程序,设计对话框资源如图18.11所示。(2)在对话框的头文件中引用“winsock2.h”头文件,并导入网络库文件。#include winsock2.h#pragma comment (lib,ws2_32.lib)(3)在应用程序的InitInstance方法中初始化套接字。WSADATA wsd;WSAStartup(MAKEWORD(2,2),&wsd);(4)在对话框类中定义成员变量,记录服务器套接字和与之连接的客户端套接字信息。SOCKET m_server,m_client;SOCKET m_ClientsMAXNUM; /客户端套接字int m_CurClient; /当前连接的客户数量(5)在对话框类的OnInitDialog方法中创建套接字,并初始化数据。/创建套接字m_server = socket(AF_INET,SOCK_STREAM,0);/将网络中的事件关联到窗口的消息函数中WSAAsyncSelect(m_server,m_hWnd,20000,FD_WRITE|FD_READ|FD_ACCEPT);m_client = 0;m_serverIP = ;for (int i = 0; i MAXNUM;i+)m_Clientsi= 0;m_CurClient = 0;(6)处理“监听”按钮的单击事件,将套接字绑定到本机地址,并开始监听套接字。void CServerDlg:OnOK() /服务器端地址sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;m_IP.GetWindowText(m_serverIP);/设置本机地址serveraddr.sin_addr.S_un.S_addr = inet_addr(m_serverIP);UpdateData(TRUE);/设置端口号serveraddr.sin_port = htons(m_port);/绑定地址if (bind(m_server,(sockaddr*)&serveraddr,sizeof(serveraddr)MessageBox(绑定地址失败.);return;/开始监听listen(m_server,50);(7)向对话框中添加HandleData方法,用于接受客户端的连接,并获得客户端传来的数据,将其转发给其他客户端。void CServerDlg:HandleData() sockaddr_in serveraddr;char buffer1024;int len =sizeof(serveraddr);/接收客户端的数据int curlink = -1;int num = -1;for (int p = 0;p MAXNUM; p+)num= recv(m_Clientsp,buffer,1024,0);if (num != -1)curlink = p;break;buffernum= 0;if (num=-1) /接受客户端的连接if (m_CurClient MAXNUM)m_Clientsm_CurClient = accept(m_server,(struct sockaddr*)&serveraddr,&len);m_CurClient+=1; return;/将接收的数据发送给客户端for (int j = 0;jmessage=20000)HandleData();return TRUE;elsereturn CDialog:PreTranslateMessage(pMsg);客户端程序设计步骤如下。ch1807实例位置:mr/18/sl/07(1)创建一个基于对话框的工程,设置对话框资源如图18.12所示。图18.12 客户端设计窗口(2)在对话框类的头文件中引用“winsock2.h”头文件,并导入“ws2_32.lib”库文件。#include winsock2.h#pragma comment (lib,ws2_32.lib)(3)在应用程序的InitInstance方法中初始化套接字。WSADATA wsd;WSAStartup(MAKEWORD(2,2),&wsd);(4)在对话框的OnInitDialog方法中创建套接字。m_client = socket(AF_INET,SOCK_STREAM,0);(5)处理“连接”按钮的单击事件,连接服务器,并设置套接字接收数据时触发的消息。void CClientDlg:OnOK() /服务器端地址sockaddr_in serveraddr;UpdateData(TRUE);serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(m_port);serveraddr.sin_addr.S_un.S_addr = inet_addr(m_IP);if (connect(m_client,(sockaddr*)&serveraddr,sizeof(serveraddr)!=0)MessageBox(连接失败);return; elseMessageBox(连接成功);WSAAsyncSelect(m_client,m_hWnd,1000,FD_READ);CString str,info ;m_name.GetWindowText(str);info.Format(%s-%s,str,进入聊天室);int i = sen

温馨提示

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

最新文档

评论

0/150

提交评论