UDP套接字编程.docx
- 文档编号:10445112
- 上传时间:2023-02-11
- 格式:DOCX
- 页数:9
- 大小:57.94KB
UDP套接字编程.docx
《UDP套接字编程.docx》由会员分享,可在线阅读,更多相关《UDP套接字编程.docx(9页珍藏版)》请在冰豆网上搜索。
UDP套接字编程
UDP套接字编程
1、服务器:
1.#include
2.#include
3.#include
4.#include
5.#include
6.#include
7.#include
8.#include
9.#definePORT1234
10.#defineMAXDATASIZE100
11.Main()
12.{
13.intsockfd;
14.structsockaddr_inserver;
15.structsockaddr_inclient;
16.socklen_tlen;
17.intnum;
18.charbuf[MAXDATASIZE];
19.if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
20.{
21.perror("Creatingsocketfailed.");
22.exit
(1);
23.}
24.bzero(&server,sizeof(server));
25.server.sin_family=AF_INET;
26.server.sin_port=htons(PORT);
27.server.sin_addr.s_addr=htonl(INADDR_ANY);
28.if(bind(sockfd,(structsockaddr*)&server,sizeof(server))==-1)
29.{
30.perror("Bind()error.");
31.exit
(1);
32.}
33.len=sizeof(client);
34.while
(1)
35.{
36.num=recvfrom(sockfd,buf,MAXDATASIZE,0,(structsockaddr*)&client,&len);
37.if(num<0)
38.{
39.perror("recvfrom()error\n");
40.exit
(1);
41.}
42.buf[num]='\0';
43.printf("Yougotamessage<%s>fromcient.\nIt'sipis%s,portis%d.\n",buf,inet_ntoa(client.sin_addr),htons(client.sin_port));
44.sendto(sockfd,"Welcome\n",8,0,(structsockaddr*)&client,len);
45.if(!
strcmp(buf,"bye"))
46.break;
47.}
48.close(sockfd);
49.}
第1~8行:
所需的头文件
第9~10行:
定义端口号和接收缓冲区的大小
第19~23行:
调用socket函数,产生UDP套接字。
如果出错,则打印错误信息。
第24~27行:
初始化server套接字地址结构,并对地址结构中的成员赋值。
当前的本地地址设为INADDR_ANY,端口号为1234,这里的端口号和IP地址都要转换成网络字节序。
第28~32行:
将套接字和指定的地址协议绑定。
第36行:
接收客户端的信息,并存放在buf中,客户端的地址信息存放在client地址结构中。
如果成功,num返回接收的字符串长度。
第37~41行,如果调用recvfrom()函数发生错误,则打印错误信息。
第43行:
显示接收到的客户信息、客户的IP地址和端口号.通过inet_ntoa()函数将IP地址转换成可显示的ASCII字符串,通过htons()函数将端口号转换成网络字节序。
第44行:
发送Welcome字符串给客户端。
第45行和46行:
如果客户端发来的字符串是"bye",则退出循环。
第48行:
关闭套接字。
2、客户端:
1.#include
2.#include
3.#include
4.#include
5.#include
6.#include
7.#include
8.#include
9.#definePORT1234
10.#defineMAXDATASIZE100
11.intmain(intargc,char*argv[])
12.{
13.intsockfd,num;
14.charbuf[MAXDATASIZE];
15.structhostent*he;
16.structsockaddr_inserver,peer;
17.if(argc!
=3)
18.{
19.printf("Usage:
%s
20.exit
(1);
21.}
22.if((he=gethostbyname(argv[1]))==NULL)
23.{
24.printf("gethostbyname()error\n");
25.exit
(1);
26.}
27.if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
28.{
29.printf("socket()error\n");
30.exit
(1);
31.}
32.bzero(&server,sizeof(server));
33.server.sin_family=AF_INET;
34.server.sin_port=htons(PORT);
35.server.sin_addr=*((structin_addr*)he->h_addr);
36.sendto(sockfd,argv[2],strlen(argv[2]),0,(structsockaddr*)&server,sizeof(server));
37.socklen_tlen;
38.len=sizeof(server);
39.while
(1)
40.{
41.if((num=recvfrom(sockfd,buf,MAXDATASIZE,0,(structsockaddr*)&peer,&len))==-1)
42.{
43.printf("recvform()error\n");
44.exit
(1);
45.}
46.if(len!
=sizeof(server)||memcmp((constvoid*)&server,(constvoid*)&peer,len)!
=0)
47.{
48.printf("Receivemessagefromotherserver.\n");
49.continue;
50.}
51.buf[num]='\0';
52.printf("ServerMessage:
%s.\n",buf);
53.break;
54.}
55.close(sockfd);
56.}
第1~8行:
所需的头文件
第9~10行:
定义端口号和缓冲区大小。
这里的端口号是要与之通讯的服务器的端口号。
第17~21行:
检查用户的输入。
如果用户输入不正确,提示用户正确的输入方式。
本例要求用户从命令行输入要发送的消息。
第22~26行:
通过用户输入的点分十进制的IP地址,获得服务器的相关地址信息。
Gethostbyname()函数将在后面介绍。
第27~31行:
调用socket()函数产生套接字描述符。
第32~35行:
初始化服务器的地址结构,并为地址结构的成员赋值。
第36行:
将用户从命令行输入的消息发送给服务器server。
第41~45行:
接收服务器发过来的字符串,并保存在buf中。
接收的真正字节数被存储在num中,同时peer返回接收服务器的地址。
第46~50行:
由于UDP套接字是无连接的,它可能接收到其它服务器发来的信息,所以应判断信息是否来自于相应的服务器。
首先,比较recvfrom()函数调用后返回的地址长度len是否等于结构体server的长度;如果不是,则说明消息来自于其它服务器;然后判断server和peer变量中的内容是否一致。
如果一致,则说明收到的信息来自于相应的服务器。
注意:
server和peer使用memcmp函数进行比较时,首先应转化成常量指针才能使用。
第51~52行:
显示来自于服务器的buf中的信息。
第55行:
关闭套接字
recvfrom函数和sendto函数的作用:
recvfrom()函数:
num=recvfrom(sockfd,buf,MAXDATASIZE,0,(structsockaddr*)&client,&len);
//接收客户端的信息,并存放在buf中,客户端的地址信息存放在client地址结构中。
如果成功,num返回接收的字符串长度。
UDP使用recvfrom()函数接收数据,它类似于标准的read(),但是在recvfrom()函数中要指明目的地址。
前面的三个参数:
sockfd、buf和len等同于函数read()的前3个参数,分别为调用socket()函数生成的描述符、指向读入缓冲区的指针和读入的字节数。
Flags参数是传输控制标志,其值如下:
(1)0:
常规操作,所做的操作与read相同。
(2)MSG_OOB:
指明要读的是外带数据而不是一般数据。
(3)MSG_PEEK:
可以查看可读的数据而不读出,在接收数据后不会将这些数据丢弃。
recvfrom函数的最后两个参数类似于accept的最后两个参数:
from返回与之通信的对方的套接字地址结构,告诉用户接收到的数据报来自于谁;最后一个参数addrlen是一个整数的指针(值-结果参数),存储数据发送者的套接字地址结构的长度。
如果recvfrom函数中的from参数是空指针,则相应的长度参数(addrlen)也必须是空指针,这表示并不关心发送数据方的协议地址。
该函数调用成功的返回值为接收到数据的长度(以字节为单位),也就是接收的数据报中用户数据的总量;如果调用失败则返回-1,并置相应的errno值。
sendto()函数:
sendto(sockfd,"Welcome\n",8,0,(structsockaddr*)&client,len);//发送Welcome字符串给客户端。
UDP使用sendto()函数发送数据,它类似于标准的write,但是与recvfrom()函数一样,sendto()函数中要指明地址。
前3个参数:
sockfd、buf、和len等同于函数read()的前3个函数,分别调用socket函数生成的描述符、指向发送缓冲区的指针和发送的字节数。
Flags参数是传输控制标志,其值如下:
(1)0:
常规操作,所做的操作与write相同。
(2)MSG_DONTROUTE:
告诉内核的主机在直接连接的本地网络上,不需要查路由表。
(3)MSG_OOB:
指明发送的是外带数据。
函数sendto的参数to的类型是套接字地址结构,指明数据将发往的协议地址,它的大小由addrlen参数来指定。
但是sendto函数中的最后一个参数是一个整数值,而不是值-结果参数。
sendto的最后两个参数类似于connect的最后两个参数:
用数据报将发往的协议地址来装填套接字地址结构。
该函数调用成功的返回值为发送数据的长度(以字节为单位);如果调用失败则返回-1,并置相应的errno值。
Recvfrom和sendto也可用于TCP协议,但是一般不这么使用。
程序实现的功能是:
(1)客户根据用户提供的IP地址将用户从终端输入的信息发送给服务器,然后等待服务器的回应。
(2)服务器接收客户端发送的信息并显示,同时显示客户的IP地址、端口号,并向客户端发送信息。
如果服务器接收的客户信息为“bye”,则退出循环,并关闭套接字。
(3)客户接收,显示服务器发回的信息,并关闭套接字。
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- UDP 套接 编程