基于UDP的服务器程序.docx
《基于UDP的服务器程序.docx》由会员分享,可在线阅读,更多相关《基于UDP的服务器程序.docx(15页珍藏版)》请在冰豆网上搜索。
![基于UDP的服务器程序.docx](https://file1.bdocx.com/fileroot1/2023-2/2/a5512374-44f1-4f9f-bfbc-b15835eb297c/a5512374-44f1-4f9f-bfbc-b15835eb297c1.gif)
基于UDP的服务器程序
摘要
1课程设计目的
网络服务是以客户机/服务器模式工作的,服务器在特定的端口上提供网络服务。
本课程设计的主要
目的的是通过编写基于UDP的服务器程序,了解客户机/服务器与UDP协议的工作原理。
2课程设计要求
根据后面介绍的UDP协议的工作原理,编写程序实现基于UDP的服务器。
1)以命令行形式运行:
UdpServerserve_port
其中,UdpServer为程序名,server_port为服务器使用的端口号。
2)输出内容:
服务器与客户端的交互过程,例如:
UDPServerRecceive:
。
。
。
UDPServerSend:
。
。
。
3相关知识
UDP协议是一种无连接的不可靠的传输层协议。
从应用层的角度来看,UDP协议在网络
层的IP协议的基础上,向应用层的程序提供不可靠的数据包传输服务。
UDP协议为上面的
应用层提供传输服务。
UDP协议主要用于对传输效率要求很高的应用层协议,例如引导协议
(BOOTP)网络时间协议(NTP)简单网络管理协议(SNMP)简单的文件传输协议(TFTP)
等。
另外,域名服务器(DNS)同时依赖于TCP与UDP协议。
由于UDP协议采用无连接的工作方式,并且只提供有限的差错控制,因此UDP协议简单并且执行效率很高。
UDP协议没有采用基于窗口的流量控制机制,当数据包过多时在接收端可能会出现溢出,
接收端无法判断在传输中出现那种错误,应用层还需要提供一定的差错控制功能。
目前,一些实用要求一恒定速率发送数据,并且在网络出现拥塞时可以丢失一些数据,但是不希望数据传输的时延太大,UDP协议正好可以适应这种需求。
基于UDP协议的网络应用也采用客户机/服务器模式。
在这里,客户机与服务器表示互相通信的两个应用程序的进程,它们分别被称为UDP客户机与UDP服务器。
UDP服务器是指提供某种网络服务的应用进程,它通过熟知端口号来向客户提供服务。
3.2TCP/IP协议技术
在TCP/IP协议族中,有两个互不相同的传输协议:
TCP(传输控制协议)和UDP(用户数据报协议)。
TCP为两台主机提供高可靠性的数据通信。
它所做的工作包括把应用程序交给它的数据分成合适的小块交给下面的网络层,确认接收到的分组,设置发送最后确认分组的超时时钟等。
由于运输层提供了高可靠性的端到端的通信,因此应用层可以忽略所有这些细节。
而另一方面,UDP则为应用层提供一种非常简单的服务。
它只是把称作数据报的分组从一台主机发送到另一台主机,但并不保证该数据报能到达另一端。
任何必需的可靠性必须由应用层来提供。
3.3TCP/IP协议与Winsock网络编程接口
Winsock规范不是一种网络协议,而是一套开放的、支持多种协议的Windows写的网络编程接口。
Winsock可以访问很多种网络协议,可以把它当作一种协议的封装。
现在的Winsock已经基本上实现了与协议无关,可以使用Winsock来调用协议的功能
3.4WINSOCKAPI的应用
主要涉及到的函数:
(1)WSAStartup函数,基本格式为intWSAtartup(WORDwVersionRequestted,LPWSADATAlpWSAData);
(2)WSACleanup函数,其基本格式为intWSACleanup(void);
(3)socket函数,其格式为socket(intaf,inttype,intprotocol);用于创建一个能够进行网络通信的套接字。
(4)closesocket函数格式为:
intclosesocket(SOCKETs);用来关闭一个描述符为s的套接字。
(5)send函数格式为:
intsend(SOCKETs,constcharFAR*buf,intlen,intflags);向TCP连接的另一端发送数据。
(6)recv函数格式为:
intrecv(SOCKETs,charFAR*buf,intlen,intflags);用来从TCP的另一端接收数据。
(7)bind函数格式为:
intbind(SOCKETs,conststructsockaddrFAR*name,intnamelen);用来给SOCKET绑定一个IP地址和端口号。
(8)listen函数格式为:
intlisten(SOCKETs,intbacklog);使流套接字S处于监听状态。
(9)accept函数格式为:
SOCKETaccept(SOCKETs,structsockaddrFAR*addr,intFAR*addrlen);该函数从监听状态的的流套接字S的客户连接请求队列取出排在最前面的客户请求,并且创建一个新的套接字来与客户套接字创建连接通道。
(10)connect函数格式为:
intconnect(SOCKETs,conststructsockaddrFAR*name,intnamelen);使用该函数使客户Socke与监听与计算机特定端口上的服务Socket进行连接,这台计算机由name指定。
4课程设计分析
首先编写两个程序分别为客户器与服务器,使得两者建立连接,在客户器中发送命令然后等待服务器提供相应的反映,具体实现如下:
对于UDP服务器端,服务程序首先调用套接口函数socket(),然后调用绑定IP地址和协议端口号函数bind()。
之后调用函数recvfrom()接收客户数据,调用sendto()向客户发送数据。
对于UDP客户端,客户机程序启动后调用套接口函数socket(),然后调用sendto()向服务器发送数据,调用recvfrom()接收服务器数据。
双方数据交换成功后,各自调用关闭套接口函数close()关闭套接口。
UDP套接口通信方式。
具体流程图如下:
流程图二:
程序二:
客户机端程序
#include
#include
#include
#defineDEFAULT_PORT5050
#defineDATA_BUFFER1024
#pragmacomment(lib,"WS2_32.lib")
voidmain(intargc,char*argv[])
{
WSADATAwsaData;
SOCKETsClient;
intiPort=5050;
intiLen;
intisend,iRecv;
charsend_buf[]="Hello!
Iamaclient";
charrecv_buf[DATA_BUFFER];
structsockaddr_inser;
if(argc<2)
{
printf("输入服务器的IP地址:
\n");
return;
}
else
memset(recv_buf,0,sizeof(recv_buf));
if(WSAStartup(MAKEWORD(2,2),&wsaData)!
=0)
{
printf("Winsock环境初始化失败:
\n");
return;
}
sClient=socket(AF_INET,SOCK_DGRAM,0);
if(sClient==INVALID_SOCKET)
{
printf("socket()函数调用失败:
%d\n",WSAGetLastError());
return;
}
ser.sin_family=AF_INET;
ser.sin_port=htons(iPort);
ser.sin_addr.s_addr=inet_addr(argv[1]);
iLen=sizeof(ser);
isend=sen
5.程序代码
5#include
6#include
7#pragmacomment(lib,"WS2_32")//链¢¡ä接¨®到Ì?
WS2_32.lib
8BOOLInitWinsock();
9voidmain()
10{
11SOCKETsocket1;
12
13InitWinsock();
14structsockaddr_inserver;
15intlen=sizeof(server);
16server.sin_family=AF_INET;
17server.sin_port=htons(1000);///server的Ì?
监¨¤听¬y端?
口¨²
18server.sin_addr.s_addr=inet_addr("127.1.1.1");///server的Ì?
地Ì?
址¡¤
19
20socket1=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
21while
(1)
22charbuffer[1024]="\0";
23{
24
25printf("UDPNeederpleaseinputmessage\n");
26scanf("%s",buffer);
27if(strcmp(buffer,"bye")==0)
28break;
29if(sendto(socket1,buffer,sizeofbuffer,0,(structsockaddr*)&server,len)!
=SOCKET_ERROR)
30{printf("UDPNeederSend:
%s\n",buffer);
31if(recvfrom(socket1,buffer,sizeofbuffer,0,(structsockaddr*)&server,&len)!
=SOCKET_ERROR)
32printf("ReceivefromUDP:
%s\n",buffer);
33}
34}
35closesocket(socket1);
36}
37
38BOOLInitWinsock()
39{
40intError;
41WORDVersionRequested;
42WSADATAWsaData;
43VersionRequested=MAKEWORD(2,2);
44Error=WSAStartup(VersionRequested,&WsaData);//启?
动¡¥WinSock2
45if(Error!
=0)
46{
47returnFALSE;
48}
49else
50{
51if(LOBYTE(WsaData.wVersion)!
=2||HIBYTE(WsaData.wHighVersion)!
=2)
52{
53WSACleanup();
54returnFALSE;
55}
56
57}
58returnTRUE;
59}
60
61#include
62#include
63#include
64#pragmacomment(lib,"WS2_32")//链¢¡ä接¨®到Ì?
WS2_32.lib
65BOOLInitWinsock();
66voidmain()
67{
68SOCKETsocket1;
69
70InitWinsock();
71structsockaddr_inlocal;
72structsockaddr_infrom;
73intfromlen=sizeof(from);
74local.sin_family=AF_INET;
75local.sin_port=htons(1000);///监¨¤听¬y端?
口¨²
76local.sin_addr.s_addr=INADDR_ANY;///本À?
机¨²
77
78socket1=socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
79
80bind(socket1,(structsockaddr*)&local,sizeoflocal);
81
82while
(1)
83{
84charbuffer[1024]="\0";
85printf("UDPServerwaitingformessagefromothers-------------\n\n");
86if(recvfrom(socket1,buffer,sizeofbuffer,0,(structsockaddr*)&from,&fromlen)!
=SOCKET_ERROR)
87{
88printf("UDPServerReceive:
%s\n",buffer);
89////给?
cilent发¤¡é信?
息¡é
90if(strcmp(buffer,"gettime")==0)
91{
92//获?
得Ì?
当Ì¡À前¡ã系¦Ì统ª3时º¡À间?
93time_tCurTime;
94time(&CurTime);
95strftime(buffer,sizeof(buffer),"%Y-%m-%d%H:
%M:
%S",localtime(&CurTime));
96sendto(socket1,buffer,sizeofbuffer,0,(structsockaddr*)&from,fromlen);}
97printf("UDPServersend:
%s\n",buffer);
98sendto(socket1,buffer,sizeofbuffer,0,(structsockaddr*)&from,fromlen);
99}
100Sleep(500);
101}
102
103closesocket(socket1);
104
105
106}
107
108BOOLInitWinsock()
109{
110intError;
111WORDVersionRequested;
112WSADATAWsaData;
113VersionRequested=MAKEWORD(2,2);
114Error=WSAStartup(VersionRequested,&WsaData);//启?
动¡¥WinSock2
115if(Error!
=0)
116{
117returnFALSE;
118}
119else
120{
121if(LOBYTE(WsaData.wVersion)!
=2||HIBYTE(WsaData.wHighVersion)!
=2)
122{
123WSACleanup();
124returnFALSE;
125}
126
127}
128returnTRUE;
129}
运行结果与分析
(运行结果是否正确,课程设计过程中出现的问题及其解决方案,可扩充的功能及设计等。
)
客户器在此页面可以输出命令,来等待服务器作出反应。
客户器输出命令语句等待服务器反应。
此图为客户器输出计算机三班张朝辉的课设组作业的反应界面。
7参考文献
[1]谢希仁编著.计算机网络(第5版).北京:
电子工业出版社,2008
[2]吴宜功吴英编著.计算机网络课程设计(第2版).北京:
机械工业出版社,2012