您好,欢迎访问三七文档
当前位置:首页 > 行业资料 > 交通运输 > UDP_winsocket简单示例讲解.
2015.9.21曹亚帅UDP_WINSOCK三枚铜钱工作室2015.9.21UDP用最通俗的话讲,所谓UDP,就是发送出去就不管的一种网络协议。因此UDP编程的发送端只管发送就可以了,不用检查网络连接状态。下面用例子来说明怎样编写UDP,并会详细解释每个API和数据类型。2015.9.21UDP协议模式2015.9.21【原创分享】Win32Socket简单示例用简单的代码和演示说明了WinSocket的使用一般必要步骤。先看看程序执行的效果吧:2015.9.21最上面的一个窗口为服务端,下面的窗口为客户端;服务端的主循环负责接收数据。如果客户端输出“exit/quit”字符串的话,则服务端和客户端程序终止。这个示例主要是通过简单的代码让初学者了解到WSA(WinSocketAPI)的启动相关的函数和参数,以及收发相关的两个函数的使用,最后释放WS资源。可以理解为一个最小的C/S演示。2015.9.21对于聊天程序来说,即使丢失一些数据,也不会影响信息的交流,可以根据上下文的情况,知道对方所要表达的意思,或者根据对方的信息,重新发送我们所说的话。对于TCP来说,在通信前,需要经过三步握手协议以建立连接,而建立过程往往是比较消耗时间的。建立连接后,在聊天过程中,可能经过好长一段时间,双方才会说一句话,那么连接应该保持还是应先断开,等对方说话时再建立呢?也就是说,TCP协议的面向连接、数据确认和重传机制将会影响聊天的效率。所以对于聊天类的软件来说,通常都采用基于UDP的方式来实现。其特点就是不需要建立连接,也没有数据确认和重传机制,因此适时性较高。2015.9.21本示例的基本实现过程是:客户端通过键盘输入数据,数据被发送到服务器。后者接收到数据后,需要进行判断,如果发来的数据串为quit,表明对方向退出聊天过程,于是服务器端也发送字符串quit,聊天过程终止;否则将接收到的信息和对方的IP地址进行格式化后,在屏幕上输出。同样在客户端也需要进行相应的判断和输出。2015.9.21TCP协议模式2015.9.21UDP网络程序编写基于UDP(面向无连接)的socket编程服务器(接收端)程序1.创建套接字(socket)2.将套接字绑定到一个本地地址和端口上(bind)3.等待接收数据(recvfrom)4.关闭套接字客户端(发送端)程序1.创建套接字(socket)2.向服务器端发送数据(sendto)3.关闭套接字2015.9.21服务端:2015.9.21/*ChatServerCPP*/#pragmacomment(lib,ws2_32.lib)//winsocket2需要的库文件#includeWINSOCK2.H//winsocket2的头文件(对于Winsock2.0应包括Winsock2.h文件)#includestdio.h2015.9.21WSADATA类型是一个结构,描述了Socket库的一些相关信息,其结构定义如下:typedefstructWSAData{WORDwVersion;WORDwHighVersion;charszDescription[WSADESCRIPTION_LEN+1];charszSystemStatus[WSASYS_STATUS_LEN+1];unsignedshortiMaxSockets;unsignedshortiMaxUdpDg;charFAR*lpVendorInfo;}WSADATA;wVersionRequested=MAKEWORD(2,0);注意低位内存存储主版本号2,高位内存存储副版本号0,其值为0x0002。使用宏LOBYTE可以读取WORD的低位字节,HIBYTE可以读取高位字节。2015.9.21voidmain(){/*第一步:初始化WINSOCK*/WORDwVersionRequested;//应用程序所需的Winsock版本号WSADATAwsaData;//用来返回Winsock实现的细节信息interr;//出错代码wVersionRequested=MAKEWORD(1,1);//生成版本号1.1err=WSAStartup(wVersionRequested,&wsaData);//调用初始化函数if(err!=0){return;}//通知用户找不到合适的DLL文件返回值为零的时候是表示成功申请WSAStartup2015.9.21//确认返回的版本号是客户要求的1.1;否则的话,调用WSACleanup()清除信息,结束函数if(LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1){WSACleanup();//调用函数解除与Winsock.DLL库的绑定,释放Winsock实现分配给应用程序的系统资源,中止对WindowsSocketsDLL的使用return;}//至此,可以确认初始化成功,Winsock.DLL可用;如果不是1.1的则退出/*第二步:创建套接口;建立一个socket*/SOCKETsockSrv=socket(AF_INET,SOCK_DGRAM,0);//创建一个数据报套接字;AF_INET是IPV4的标志;SOCK_DGRAM是UDP数据包的标志;创建socket服务,使用udp协议2015.9.21专门针对Internet通信域的Winsock地址结构structsockaddr_in{short.sin_family;//指定地址家族,一定是AF_INET.u_shortsin_port;//指定将要分配给套接字的传输层端口号structin_addrsin_addr;//指定套接字的主机的IP地址charsin_zero[8];//全置为0,是一个填充数}WinsockAPI特为此设置了四个函数(1)htonl()将主机的无符号长整型数本机顺序转换为网络字节顺序(HosttoNetworkLong),用于IP地址。u_longPASCALFARhtonl(u_longhostlong);hostlong是主机字节顺序表达的32位数。htonl()返回一个网络字节顺序的值。2015.9.21/*第三步:填充sockaddr_in结构*/SOCKADDR_INaddrSrv;//定义一个Sockaddr_in型的结构实例变量//指定套接字的主机的IP地址;一台机器可以用很多个IP,也可以制定为INADDR_ANY,这样会对所有有效IP都适用addrSrv.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//服务器绑定的IP是任意的;转换Unsignedshort为网络字节序的格式addrSrv.sin_family=AF_INET;//指定地址家族,一定是AF_INET;指定通信域是InternetaddrSrv.sin_port=htons(7000);//指定将要分配给套接字的传输层端口号;指定端口,将端口号转换为网络字节顺序2015.9.21在使用Internet域的套接字时,这三个数据结构的一般用法是:首先,定义一个Sockaddr_in的结构实例变量,并将它清零。然后,为这个结构的各成员变量赋值;第三步,在调用BIND()绑定函数时,将指向这个结构的指针强制转换为sockaddr*类型。2015.9.21/*第四步:将套接口绑定到指定的网络地址BIND()*///开始绑定这个服务器,用创建好的SOCKET对象和服务器IP信息、以及服务器IP信息的长度;将套接字绑定到一个本地地址和端口上(bind)bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));//第二参数要强制类型转换;将套接字绑定到指定的网络地址,对&addrSrv进行了强制类型转换/*第五步:接收数据*///申请变量charrecvBuf[100];//接收数据包charsendBuf[100];//发送数据包chartempBuf[200];//临时存储区SOCKADDR_INaddrClient;intlen=sizeof(SOCKADDR);//sockaddr结构的长度;初始化这个参数,这个参数必须被初始化2015.9.21while(1)//不断等待客户端请求的到来{//从客户端接收应答消息;接受数据到recvBuf[100]recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len);//如果接收的应答字符串为“quit”,则告知对方对话结束if(!strcmp(quit,recvBuf)){//向客户端提交字符串数据包sendto(sockSrv,quit,strlen(quit)+1,0,(SOCKADDR*)&addrClient,len);printf(Chatend!\n);break;}2015.9.21sprintf(tempBuf,%ssay:%s,inet_ntoa(addrSrv.sin_addr),recvBuf);//将sin_addr储存的IP(数值)转换成字符串形式(127.0.0.1)。2015.9.21//打印出对方聊天的IP和聊天内容sprintf(tempBuf,%ssay:%s\n,inet_ntoa(addrClient.sin_addr),recvBuf);printf(“%s\n,tempBuf);//如果不是Q则将客户端的IP地址和发送的数据格式化完放到tempBUf中printf(“请输入对话:\n);gets(sendBuf);//从标准输入流中获取一行数据sendto(sockSrv,sendBuf,strlen(sendBuf)+1,0,(SOCKADDR*)&addrClient,len);//将用户输入的数据发送到客户端;向客户端提交字符串数据包}/*第六步:关闭socket,释放网络*/closesocket(sockSrv);WSACleanup();}2015.9.21客户端:2015.9.21/*ChatClientCPP*/#pragmacomment(lib,ws2_32.lib)#includeWINSOCK2.H#includestdio.h2015.9.21voidmain(){//加载socket动态链接库(dll)WORDwVersionRequested;WSADATAwsaData;//这结构是用于接收WindowsSocket的结构信息的interr;wVersionRequested=MAKEWORD(1,1);//请求1.1版本的WinSock库err=WSAStartup(wVersionRequested,&wsaData);if(err!=0){return;}//返回值为零的时候是表示成功申请WSAStartup/*第一步:初始化WINSOCK*/2015.9.21if(LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1){WSACleanup();return;}//检查这个低字节是不是1,高字节是不是1以确定是否我们所请求的1.1版本//否则的话,调用WSACleanup()清除信息,结束函数2015.9.21SOCKADDR_INaddrSrv;//初始化SOCKADDR_IN,IP,端口addrSrv.sin_addr.S_un.S_addr=inet_addr(“127.0.0.1”);//本地回路地址是127.0.0.1;设置要连接的主机IP,这里用一台机做试验addrSrv.sin_family=AF_INET;addrSrv.sin_port=htons(7000);/*第二步:创建套接口;建立一个socket*/SOCKETsockClient=socket(AF_INET,SOCK_DGRAM,0);/*第三步:填充s
本文标题:UDP_winsocket简单示例讲解.
链接地址:https://www.777doc.com/doc-2864352 .html