首页 新闻 论坛 群组 Blog 文档 下载 读书 Tag 网摘 搜索 开源 FAQ 第二书店 博文视点 程序员
频道: 研发 数据库 中间件 信息化 视频 .NET Java 游戏 移动 服务: 人才 外包 培训
    图书品种:235680
       
热门搜索: ASP.NET Ajax Spring Hibernate Java

3-6说明了怎样通过套接字标识符在发送数据时指定目标地址及端口并发送UDP数据报。

3-6  sendto( )函数发送UDP数据报(udp3.c)

1   /*

2    * udp3.c

3    *

4    * send UDP datagram using socket

5    * descriptor and sendto(). example

6    * program #3.

7    *

8    * foster <jamescfoster@gmail.com>

9  */

10

11 #include <stdio.h>

12

13 #include <sys/socket.h>

14 #include <netinet/in.h>

15 #include <arpa/inet.h>

16

17 #define UDP3_DST_ADDR "127.0.0.1"

18 #define UDP3_DST_PORT 1234

19

20 int

21 main(void)

22 {

23          struct sockaddr_in sin;

24          char buf[100];

25         int sock = 0;

26         int ret = 0;

27

28         sock = socket(AF_INET, SOCK_DGRAM, 0);

29         if(sock < 0)

30         {

31                  printf("socket() failed.\n");

32                  return(1);

33         }

34

35         memset(&sin, 0x0, sizeof(sin));

36

37         sin.sin_family       = AF_INET;

38         sin.sin_port         = htons(UDP3_DST_PORT);

39         sin.sin_addr.s_addr = inet_addr(UDP3_DST_ADDR);

40

41         memset(buf, 'A', 100);

42

43         ret = sendto(sock, buf, 100, 0,

44         (struct sockaddr *) &sin, sizeof(sin));

45         if(ret != 100)

46         {

47                 printf("sendto() failed.\n");

48                 return(1);

49         }

50

51         close(sock);

52         printf("sendto() success.\n");

53

54         return(0);

55 }

编译

obsd32# gcc -o udp3 udp3.c

执行

obsd32# ./udp3

sendto() success.

分析

udp3.c示例了使用sendto( )函数发送数据的另一种可选方法。使用sendto( )函数发送数据时,数据的目标地址是由每次调用时的第5个参数(sockaddr_in型的结构)指定的,而不是事先调用connect( )函数,这样允许使用一个套接字描述符发送数据到不同的目标地址。当数据必须发送到不同的目标时,如实现基于UDP的扫描器,sendto( )函数将十分有用。

udp3.cudp2.c之间的区别在于没有调用connect( )函数,并且用sendto( )函数代替了send( )函数。例3-7说明了怎样使用recvfrm( )函数接收UDP数据报。

3-7  接收UDP数据报(udp4.c)

1   /*

* udp4.c

3    *

4    * receive UDP datagram using

5    * recvfrom() function. example

6    * program #4.

7    *

8    * foster <jamescfoster@gmail.com>

9   */

10

11 #include <stdio.h>

12

13 #include <sys/socket.h>

14 #include <netinet/in.h>

15

16 #define UDP4_PORT 1234

17

18 int

19 main(void)

20 {

21      struct sockaddr_in sin;

22      char buf[100];

23    int sock = 0;

24     int ret = 0;

25

26      sock = socket(AF_INET, SOCK_DGRAM, 0);

27      if(sock < 0)

28      {

29              printf("socket() failed.\n");

30              return(1);

31      }

32

33      memset(&sin, 0x0, sizeof(sin));

34

35      sin.sin_family       = AF_INET;

36      sin.sin_port         = htons(UDP4_PORT);

37      sin.sin_addr.s_addr = INADDR_ANY;

38

39      ret = bind(sock, (struct sockaddr *) &sin, sizeof(sin));

40      if(ret < 0)

41      {

42              printf("bind() failed.\n");

43              return(1);

44      }

45

46      ret = recvfrom(sock, buf, 100, 0, NULL, NULL);

47      if(ret < 0)

48      {

49              printf("recvfrom() failed.\n");

50              return(1);

51      }

52

53      close (sock);

54      printf("recvfrom() success.\n");

55

56      return(0);

57 }

编译

obsd32# gcc -o udp4 udp4.c

执行

obsd32# ./udp4 &

[1] 18864

obsd32# ./udp3

recvfrom() success.

sendto() success.

[1] + Done ./udp4

程序udp4.c创建了一个UDP套接字,将套接字绑定到1234号端口,并等待接收UDP数据报。在执行过程中,首先执行程序udp4,之后再执行程序udp3。程序udp3向程序udp4发送了一个UDP数据报。

分析

       13行和第14行,载入sys/socket.hnetinet/in.h两个头文件。

       16行,声明UDP套接字将要绑定的端口,在本例中是1234

       26行,使用socket()函数创建一个套接字标识符,与前面的示例相似。

       32行到第36行,初始化sockaddr_in结构,用来指定将要绑定该套接字的本地端点的IP地址和端口,其中sin_familysin_port两个成员的处理方法与前面的示例相同,sin_addr.s_addr成员赋值为整型常量INADDR_ANY,表示将套接字绑定到系统中任意可用的IP地址上。例如,如果程序运行在一台有两个网络接口的主机上,每个接口都有不同的IP地址,则套接字将绑定到这两个接口上,并且在两个接口上都是可用的。将指定的网络接口的IP地址赋值给sin_addr.s_ addr成员,也可以将套接字绑定到单个的网络接口上。

       39行,调用bind()函数,将套接字绑定到sockaddr_in结构中所定义的本地端点。第1个参数为要绑定的套接字标识符;第2个参数为sockaddr_in结构的地址,必须转换为sockaddr结构指针类型;第3个参数为sockaddr_in结构的字节数。如果执行成功,bind()函数将返回一个非负整型值;如果发生错误,则返回一个负的整型值。

       46行,使用recvfrom()函数接收单个UDP数据报。其中,传给函数的第1个参数为绑定的套接字标识符;第2个参数为缓冲区地址,用来存储接收到的数据;第3个参数为缓冲区的长度;第4个参数可以是一个指向sockaddr_in结构并转换为sockaddr*类型的指针;第5个参数可以是一个整型指针,指向一个表示sockaddr_in结构长度的整数(以字节为单位)

       53行,套接字被close()函数关闭,不可再用来接收数据。

查看所有评论(0)条】

最近评论



正在载入评论列表...
热点评论