UDP套接字编程.docx

上传人:b****8 文档编号:10445112 上传时间:2023-02-11 格式:DOCX 页数:9 大小:57.94KB
下载 相关 举报
UDP套接字编程.docx_第1页
第1页 / 共9页
UDP套接字编程.docx_第2页
第2页 / 共9页
UDP套接字编程.docx_第3页
第3页 / 共9页
UDP套接字编程.docx_第4页
第4页 / 共9页
UDP套接字编程.docx_第5页
第5页 / 共9页
点击查看更多>>
下载资源
资源描述

UDP套接字编程.docx

《UDP套接字编程.docx》由会员分享,可在线阅读,更多相关《UDP套接字编程.docx(9页珍藏版)》请在冰豆网上搜索。

UDP套接字编程.docx

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\n",argv[0]);

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)客户接收,显示服务器发回的信息,并关闭套接字。

 

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 农林牧渔 > 林学

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1