• 组播,单播和广播相关


    一,定义:

    1,单播用于两个主机之间的端对端通信,广播用于一个主机对整个局域网上所有主机上的数据通信。单播和广播是两个极端,单播对一个主机进行通信,广播对整个局域网上的主机进行通信。

    多播,也称为“组播”,将局域网中同一业务类型主机进行了逻辑上的分组,进行数据收发的时候其数据仅仅在同一分组中进行,其他的主机没有加入此分组不能收发对应的数据。

    2,IP地址 和 子网掩码的概念
    (1)IP地址的概念和分类
     IP地址本质就是在互联网中的唯一地址标识,其数据类型为32位二进制组成的整数(ipv4),当然也有128位二进制组成的整数(ipv6)。日常生活中描述IP地址的主要形式为: 点分十进制表示法,也就是将每8位二进制转换为一个十进制整数,不同的十进制整数之间通过小数点分隔;
    如:0x01020304  =>  1.2.3.4

    查看IP地址的方式:
         windows系统中: ipconfig    ipconfig/all
         linux系统中: ifconfig    /sbin/ifconfig

         IP地址主要分为两部分:  网络地址  +  主机地址,根据网络地址和主机地址的划分,将IP地址分为以下4类:
         A类:0 + 7位网络地址 +  24位主机/本地地址
         B类:10 + 14位网络地址 + 16位主机/本地地址
         C类:110 + 21位网络地址 + 8位主机/本地地址
         D类:1110 + 28位多播地址

    (2)子网掩码的概念
         子网掩码本质就是用于帮助IP划分具体的网络地址和主机地址,也可以用于判断两个IP地址是否在同一个局域网中,具体的划分方法为:按位&运算进行
    如:
        IP地址:172.30.100.41
        子网掩码:255.255.255.0 

    3,端口号和字节序的概念
    (1)端口号
         IP地址 - 互联网中的地址标识,通过该地址可以定位主机
         端口号 - 主要用于定位某一台主机上的具体进程
         端口号的数据类型是:unsigned short类型,范围是:0 ~ 65535,其中0 ~ 1024之间的端口由系统占用,因此编程指定端口号时,建议从1025开始使用
         网络编程中需要提供:IP地址  +  端口号

    (2)字节序的概念
    小端系统:低位内存地址存放低位数据的系统
    大端系统:低位内存地址存放高位数据的系统
    如:对于十六进制的数据 0x12345678来说
    小端系统中按照地址从小到大依次:0x78 0x56 0x34 0x12
    大端系统中按照地址从小到大依次:0x12 0x34 0x56 0x78

    二,单播(分为tcp和udp一对一)

    1,基于Socket的一对一通信模型
    基本概念: Socket  -  本意为插座的意思,表示逻辑上的通信载体

    基本模型:
    服务器:
        (1)创建socket,使用socket函数
        (2)准备通信地址,使用结构体变量
        (3)绑定socket和    通信地址,使用bind函数
        (4)进行通信,使用read/write函数
        (5)关闭socket,使用close函数
    客户端:
        (1)创建socket,使用socket函数
        (2)准备通信地址,是服务器的地址
        (3)连接socket和通信地址,使用connect函数
        (4)进行通信,使用read/write函数
        (5)关闭socket,使用close函数

    2,.基于tcp协议的网络通信模型
    服务器:
         (1)创建socket,使用socket函数
         (2)准备通信地址,使用结构体类型
         (3)绑定socket和通信地址,使用bind函数
         (4)监听,使用listen函数
         (5)响应客户端的连接请求,使用accept函数
         (6)进行通信,使用read/write函数
         (7)关闭socket,使用close函数
    客户端:
         (1)创建socket,使用socket函数
         (2)准备通信地址,使用服务器的地址
         (3)连接socket和通信地址,使用connect函数
         (4)进行通信,使用read/write函数
         (5)关闭socket,使用close函数

    3,基于udp协议的通信模型

    服务器:
         (1)创建socket,使用socket函数
         (2)准备通信地址,使用结构体类型
         (3)绑定socket和通信地址,使用bind函数
         (4)进行通信,使用sendto/recvfrom函数
         (5)关闭socket,使用close函数
    客户端:
         (1)创建socket,使用socket函数
         (2)准备通信地址,使用服务器的地址
         (3)进行通信,使用sendto/recvfrom函数
         (4)关闭socket,使用close函数

    三,组播

    1,实际情况下经常需要对一组特定的主机进行通信,而不是整个局域网上的所有主机,这就是组播的用途。组播的地址是特定的,D类IP地址用于组播地址,即224.0.0.0至239.255.255.255之间的IP地址,并被划分为局部连接组播地址、预留组播地址和管理权限组播地址3类:

    局部组播地址:在224.0.0.0~224.0.0.255之间,这是为路由协议和其他用途保留的地址,路由器并不转发属于此范围的IP包。
    预留组播地址:在224.0.1.0~238.255.255.255之间,可用于全球范围(如Internet)或网络协议。
    管理权限组播地址:在239.0.0.0~239.255.255.255之间,可供组织内部使用,类似于私有IP地址,不能用于Internet,可限制组播范围。

    1. 属于永久组的地址:
    2. 224.0.0.1 所有组播主机
    3. 224.0.0.2 所有组播路由器
    4. 224.0.0.4 DRMRP路由器
    5. 224.0.0.5 所有OSPF的路由器
    6. 224.0.0.6 OSPF指派路由器
    7. 224.0.0.9 RPIv2路由器
    8. 224.0.0.10 EIGRP路由器
    9. 224.0.0.13 PIM路由器
    10. 224.0.0.22 IGMPv3
    11. 224.0.0.25 RGMP
    12. 224.0.1.1 NTP网络时间协议

     2,组播编程流程

    (1)建立一个socket;
    (2)设置组播的参数,例如超时时间TTL,本地回环许可LOOP等
    (3)加入组播组
    (4)发送和接收数据
    (5)从组播组离开

    3,组播主机的三个级别:

    0级:主机不能发送或接收I P组播。

    这种主机应该自动丢弃它收到的具有D类目的地址的分组。

    1级:主机能发送但不能接收I P组播。

    在向某个I P组播组发送数据报之前,并不要求主机加入该组。组播数据报的发送方式与单播一样,除了组播数据报的目的地址是 I P组播组之外。网络驱动器必须能 够识别出这个地址,把在本地网络上组播数据报。

    2级:主机能发送和接收I P组播。

    为了接收I P组播,主机必须能够加入或离开组播组,而且必须支持IGMP,能够在至少一个接口上交换组成员信息。多接口主机必须支持在它的接口的一个子网上的组播Net/3符合2级主机要求,可以完成组播路由器的工作。与单播IP选路一样,我们假定所描述的系统是一个组播路由器,并加上了Net/3组播选路的程序。

    4,组播程序设计

    使用setsockopt()函数和getsockopt()函数来实现,组播的选项是IP层的。

    **getsockopt()/setsockopt()**的选项含义

    1. IP_MULTICAST_TTL
    2. 设置组播组数据的TTL值
    3. IP_ADD_MEMBERSHIP
    4. 在指定接口上加入组播组
    5. IP_DROP_MEMBERSHIP
    6. 退出组播组
    7. IP_MULTICAST_IF
    8. 获取默认接口或设置接口
    9. IP_MULTICAST_LOOP
    10. 禁止组播数据回送

    (1)选项IP_MULTICASE_TTL

    选项IP_MULTICAST_TTL允许设置超时TTL,范围为0~255之间的任何值,

    例如:unsigned char ttl=255;   setsockopt(s,IPPROTO_IP,IP_MULTICAST_TTL,&ttl,sizeof(ttl));
    (2)选项IP_MULTICAST_IF

    选项IP_MULTICAST_IF用于设置组播的默认默认网络接口,会从给定的网络接口发送,另一个网络接口会忽略此数据。例如:

    struct in_addr addr;

    setsockopt(s,IPPROTO_IP,IP_MULTICAST_IF,&addr,sizeof(addr));

    参数addr是希望多播输出接口的IP地址,使用INADDR_ANY地址回送到默认接口。

    默认情况下,当本机发送组播数据到某个网络接口时,在IP层,数据会回送到本地的回环接口,选项IP_MULTICAST_LOOP用于控制数据是否回送到本地的回环接口。例如:

    unsigned char loop;

    setsockopt(s,IPPROTO_IP,IP_MULTICAST_LOOP,&loop,sizeof(loop));参数loop设置为0禁止回送,设置为1允许回送。
    (3)选项IP_ADD_MEMBERSHIP和IP_DROP_MEMBERSHIP

    加入或者退出一个多播组,通过选项IP_ADD_MEMBERSHIP和IP_DROP_MEMBER- SHIP,对一个结构struct ip_mreq类型的变量进行控制,struct ip_mreq原型如下:

    1. struct ip_mreq
    2. {
    3. struct in_addr imn_multiaddr;/*加入或者退出的广播组IP地址*/
    4. struct in_addr imr_interface;/*加入或者退出的网络接口IP地址*/
    5. };

    选项IP_ADD_MEMBERSHIP用于加入某个多播组,之后就可以向这个多播组发送数据或者从多播组接收数据。此选项的值为mreq结构,成员imn_multiaddr是需要加入的多播组IP地址,成员imr_interface是本机需要加入广播组的网络接口IP地址。例如:

    struct ip_mreq mreq;

    setsockopt(s,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(mreq));

    5,linux下组播服务器和客户端编程一:

    (1)服务器

    持续向多播IP地址"224.0.0.22"的0x8006端口发送数据"BROADCAST TEST DATA",发送间隔5s。

    1. /*
    2. *broadcast_server.c -组播服务程序
    3. */
    4. #define MCAST_PORT 0x8006;
    5. #define MCAST_ADDR “224.0.0.22”//*一个局部连接多播地址,路由器不进行转发*/
    6. #define MCAST_DATA “BROADCAST TEST DATA”/*组播发送的数据*
    7. #define MCAST_INTERVAL 5/*发送间隔时间*/
    8. int main(int argc, char*argv)
    9. {
    10. int s;
    11. struct sockaddr_in mcast_addr;
    12. s = socket(AF_INET, SOCK_DGRAM, 0);/*建立套接字*/
    13. if (s == -1)
    14. {
    15. perror(“socket()”);
    16. return -1;
    17. }
    18. memset(&mcast_addr, 0, sizeof(mcast_addr));/*初始化IP组播地址为0*/
    19. mcast_addr.sin_family = AF_INET;/*设置协议族类行为AF*/
    20. mcast_addr.sin_addr.s_addr = inet_addr(MCAST_ADDR);/*设置组播IP地址*/
    21. mcast_addr.sin_port = htons(MCAST_PORT);/*设置组播端口*/
    22. /*向组播地址发送数据*/
    23. while(1)
    24. {
    25. int n = sendto(s,/*套接字描述符*/
    26. MCAST_DATA,/*数据*/
    27. sizeof(MCAST_DATA),/*长度*/
    28. 0,
    29. (struct sockaddr*)&mcast_addr,
    30. sizeof(mcast_addr)) ;
    31. if( n < 0)
    32. {
    33. perror(“sendto()”);
    34. return -2;
    35. }
    36. sleep(MCAST_INTERVAL);/*等待一段时间*/
    37. }
    38. return 0
    39. }

    (2)客户端

    组播组的IP地址为224.0.0.22,端口为0x8006,当客户端接收到组播的数据后将打印出来。

    客户端只有在加入组播组后才能接受组播组的数据,因此组播客户端在接收组播组的数据之前需要先加入组播组,当接收完毕后要退出组播组。

    1. /**broadcast_client.c -组播的客户端*/
    2. #define MCAST_PORT 0x8006;
    3. #define MCAST_ADDR “224.0.0.22”/*一个局部连接多播地址,路由器不进行转发*/
    4. #define MCAST_INTERVAL 5/*发送间隔时间*/
    5. #define BUFF_SIZE 256/*接收缓冲区大小*/
    6. int main(int argc, char*argv[])
    7. {
    8. int s;/*套接字文件描述符*/
    9. struct sockaddr_in local_addr;/*本地地址*/
    10. int err = -1;
    11. s = socket(AF_INET, SOCK_DGRAM, 0);/*建立套接字*/
    12. if (s == -1)
    13. {
    14. perror(“socket()”);
    15. return -1;
    16. }
    17. /*初始化地址*/
    18. memset(&local_addr, 0, sizeof(local_addr));
    19. local_addr.sin_family = AF_INET;
    20. local_addr.sin_addr.s_addr = htonl(INADDR_ANY);
    21. local_addr.sin_port = htons(MCAST_PORT);
    22. /*绑定socket*/
    23. err = bind(s,(struct sockaddr*)&local_addr, sizeof(local_addr)) ;
    24. if(err < 0)
    25. {
    26. perror(“bind()”);
    27. return -2;
    28. }
    29. /*设置回环许可*/
    30. int loop = 1;
    31. err = setsockopt(s,IPPROTO_IP, IP_MULTICAST_LOOP,&loop, sizeof(loop));
    32. if(err < 0)
    33. {
    34. perror(“setsockopt():IP_MULTICAST_LOOP”);
    35. return -3;
    36. }
    37. struct ip_mreq mreq;/*加入多播组*/
    38. mreq.imr_multiaddr.s_addr = inet_addr(MCAST_ADDR); /*多播地址*/
    39. mreq.imr_interface.s_addr = htonl(INADDR_ANY); /*网络接口为默认*/
    40. /*将本机加入多播组*/
    41. err = setsockopt(s, IPPROTO_IP, IP_ADD_MEMBERSHIP,&mreq, sizeof(mreq));
    42. if (err < 0)
    43. {
    44. perror(“setsockopt():IP_ADD_MEMBERSHIP”);
    45. return -4;
    46. }
    47. int times = 0;
    48. int addr_len = 0;
    49. char buff[BUFF_SIZE];
    50. int n = 0;
    51. /*循环接收多播组的消息,5次后退出*/
    52. for(times = 0;times<5;times++)
    53. {
    54. addr_len = sizeof(local_addr);
    55. memset(buff, 0, BUFF_SIZE);/*清空接收缓冲区*/
    56. /*接收数据*/
    57. n=recvfrom(s,buff,BUFF_SIZE,0,(struct sockaddr*)&local_addr,&addr_len);
    58. if( n== -1)
    59. {
    60. perror(“recvfrom()”);
    61. }
    62. printf("Recv %dst message from server:%s ", times, buff);//打印信息
    63. sleep(MCAST_INTERVAL);
    64. }
    65. /*退出多播组*/
    66. err=setsockopt(s,IPPROTO_IP,IP_DROP_MEMBERSHIP,&mreq, sizeof(mreq));
    67. close(s);
    68. return 0;
    69. }
    70. }

    6,linux下组播编程二:

    (1)服务器代码

    1. #include <sys/types.h>
    2. #include <arpa/inet.h>
    3. #include <sys/socket.h>
    4. #include <stdio.h>
    5. #include <stdlib.h>
    6. #include <string.h>
    7. #include <errno.h>
    8. #include <netdb.h>
    9. #define BUFLEN 255
    10. int main(int argc, char **argv)
    11. {
    12. struct sockaddr_in peeraddr;
    13. struct in_addr ia;
    14. int sockfd;
    15. char recmsg[BUFLEN + 1];
    16. unsigned int socklen, n;
    17. struct hostent *group;
    18. struct ip_mreq mreq;
    19. /* 创建 socket 用于UDP通讯 */
    20. sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    21. if (sockfd < 0)
    22. {
    23. perror("socket\n");
    24. exit(errno);
    25. }
    26. printf("socket created success!!!\n");
    27. /* 设置要加入组播的地址 */
    28. bzero(&mreq, sizeof(struct ip_mreq));
    29. if (argv[1])
    30. {
    31. if ((group = gethostbyname(argv[1])) == (struct hostent *)0)
    32. {
    33. perror("gethostbyname");
    34. exit(errno);
    35. }
    36. }
    37. else
    38. {
    39. printf("you should give me a group address, 224.0.0.0-239.255.255.255\n");
    40. exit(errno);
    41. }
    42. bcopy((void *)group->h_addr, (void *)&ia, group->h_length);
    43. printf("组播地址:%s\n", inet_ntoa(ia));
    44. /* 设置组地址 */
    45. bcopy(&ia, &mreq.imr_multiaddr.s_addr, sizeof(struct in_addr));
    46. /* 设置发送组播消息的源主机的地址信息 */
    47. mreq.imr_interface.s_addr = htonl(INADDR_ANY);
    48. /* 把本机加入组播地址,即本机网卡作为组播成员,只有加入组才能收到组播消息 */
    49. if(setsockopt(sockfd,IPPROTO_IP,IP_ADD_MEMBERSHIP,&mreq,sizeof(struct ip_mreq))==-1)
    50. {
    51. perror("setsockopt");
    52. exit(errno);
    53. }
    54. socklen = sizeof(struct sockaddr_in);
    55. memset(&peeraddr, 0, socklen);
    56. peeraddr.sin_family = AF_INET;
    57. if (argv[2])
    58. {
    59. peeraddr.sin_port = htons(atoi(argv[2]));
    60. }
    61. else
    62. {
    63. peeraddr.sin_port = htons(4567);
    64. }
    65. if (argv[1])
    66. {
    67. if (inet_pton(AF_INET, argv[1], &peeraddr.sin_addr) <= 0)
    68. {
    69. printf("Wrong dest IP address!\n");
    70. exit(0);
    71. }
    72. }
    73. else
    74. {
    75. printf("no group address given, 224.0.0.0-239.255.255.255\n");
    76. exit(errno);
    77. }
    78. /* 绑定组播地址的端口和IP信息到socket上 */
    79. if(bind(sockfd,(struct sockaddr*)&peeraddr,sizeof(struct sockaddr_in))==-1)
    80. {
    81. printf("Binded failure\n");
    82. exit(0);
    83. }
    84. else
    85. {
    86. printf("binded success!!!\n");
    87. }
    88. /* 循环接收网络上来的组播消息 */
    89. for (;;)
    90. {
    91. bzero(recmsg, BUFLEN + 1);
    92. n=recvfrom(sockfd,recmsg,BUFLEN, 0,(struct sockaddr *)&peeraddr,&socklen);
    93. if (n < 0)
    94. {
    95. printf("recvfrom error in udptalk!\n");
    96. exit(errno);
    97. }
    98. else
    99. {
    100. /* 成功接收到数据报 */
    101. recmsg[n] = 0;
    102. printf("peer info:%s", recmsg);
    103. }
    104. }
    105. return 0;
    106. }

    (2)客户端代码

    1. #include <sys/types.h>
    2. #include <sys/socket.h>
    3. #include <arpa/inet.h>
    4. #include <stdio.h>
    5. #include <stdlib.h>
    6. #include <string.h>
    7. #include <errno.h>
    8. #define BUFLEN 255
    9. int main(int argc, char **argv)
    10. {
    11. struct sockaddr_in peeraddr;
    12. int sockfd;
    13. char recmsg[BUFLEN + 1];
    14. unsigned int socklen;
    15. /* 创建 socket 用于UDP通讯 */
    16. sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    17. if (sockfd < 0)
    18. {
    19. perror("socket\n");
    20. exit(errno);
    21. }
    22. printf("socket created success!!!\n");
    23. socklen = sizeof(struct sockaddr_in);
    24. /* 设置对方的端口和IP信息 */
    25. memset(&peeraddr, 0, socklen);
    26. peeraddr.sin_family = AF_INET;
    27. if (argv[2])
    28. peeraddr.sin_port = htons(atoi(argv[2]));
    29. else
    30. peeraddr.sin_port = htons(4567);
    31. if (argv[1])
    32. {
    33. /* 注意这里设置的对方地址是指组播地址,而不是对方的实际IP地址 */
    34. if (inet_pton(AF_INET, argv[1], &peeraddr.sin_addr) <= 0)
    35. {
    36. printf("wrong group address!\n");
    37. exit(0);
    38. }
    39. }
    40. else
    41. {
    42. printf("no group address!\n");
    43. exit(0);
    44. }
    45. /* 循环接受用户输入的消息发送组播消息 */
    46. for (;;)
    47. {
    48. /* 接受用户输入 */
    49. bzero(recmsg, BUFLEN + 1);
    50. if (fgets(recmsg, BUFLEN, stdin) == (char *)EOF)
    51. exit(0);
    52. /* 发送消息 */
    53. if(sendto(sockfd, recmsg, strlen(recmsg), 0,(struct sockaddr *)&peeraddr, sizeof(struct sockaddr_in)) < 0)
    54. {
    55. printf("sendto error!\n");
    56. exit(errno);
    57. }
    58. printf("client sendto success!\n");
    59. }
    60. return 0;
    61. }

    (3)运行

    1. $ gcc -o client client.c
    2. $ gcc -o server server.c
    3. $ ./client 234.1.2.3 4567
    4. socket created success!!!
    5. just to test!
    6. client sendto success!
    7. $ ./server 234.1.2.3 4567
    8. socket created success!!!
    9. 组播地址:234.1.2.3
    10. binded success!!!
    11. peer info:just to test!

    四,广播

    1,在windows上接收广播使用setsockopt结合SO_BROADAST。同样的代码不能在linux上获得同样的效果。使用tcpdump监听,可以收到了广播包:

    2,服务器端广播循环发送一个文件,客户端持续接收文件。

    ​ <服务器端或客户端谁先运行均可,文件名由命令行指定>

    服务端运行:./server wj.txt       客户端运行:./client

    (1)服务器代码

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. #include <unistd.h>
    5. #include <sys/socket.h>
    6. #include <time.h>
    7. #include <sys/types.h>
    8. #include <netinet/in.h>
    9. #include <arpa/inet.h>
    10. #include <sys/stat.h>
    11. #include <fcntl.h>
    12. #define LEN 256
    13. int main(int argc, char **argv)
    14. {
    15. struct sockaddr_in server_socket;
    16. int sockfd = 0;
    17. int on = 1;
    18. int num = 0;
    19. char msg[LEN] = {0};
    20. if (argc < 2)
    21. {
    22. perror("Usage error: need a filename\n");
    23. exit(1);
    24. }
    25. sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    26. if (sockfd < 0)
    27. {
    28. perror("socket():Create socket fails!\n");
    29. exit(1);
    30. }
    31. //设置套接字为广播模式 SO_BROADCAST
    32. setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST, &on, sizeof(on));
    33. memset(&server_socket,0,sizeof(server_socket));
    34. server_socket.sin_family = AF_INET;
    35. //inet_pton是一个IP地址转换函数,可以在将点分文本的IP地址转换为二进制网络字节序”的IP地址
    36. if (inet_pton(AF_INET, "255.255.255.255", &server_socket.sin_addr) <= 0)
    37. {
    38. perror("inet_pton():IP address is error!\n");
    39. exit(1);
    40. }
    41. server_socket.sin_port = htons(1234);
    42. int fd;
    43. int len;
    44. fd = open(argv[1],O_RDONLY);
    45. if(fd == -1)
    46. {
    47. perror("open failed\n");
    48. exit(1);
    49. }
    50. char begin_signal[LEN]="new transmission begin!\n\n";
    51. while(1)
    52. {
    53. sendto(sockfd, begin_signal, strlen(begin_signal), 0,
    54. (struct sockaddr *)&server_socket, sizeof(struct sockaddr_in));
    55. while((len = read(fd,msg,10)) > 0)
    56. {
    57. sendto(sockfd, msg, len, 0,
    58. (struct sockaddr *)&server_socket, sizeof(struct sockaddr_in));
    59. }
    60. lseek(fd,0,SEEK_SET); //移动读指针至文件起始位置
    61. sleep(3);
    62. }
    63. close(fd);
    64. close(sockfd);
    65. exit(0);
    66. }

    (2)客户端代码

    1. #include <stdio.h>
    2. #include <stdlib.h>
    3. #include <string.h>
    4. #include <unistd.h>
    5. #include <sys/socket.h>
    6. #include <time.h>
    7. #include <sys/types.h>
    8. #include <netinet/in.h>
    9. #include <arpa/inet.h>
    10. #define LEN 256
    11. int main(int argc, char **argv)
    12. {
    13. struct sockaddr_in client_socket;
    14. int sockfd = 0;
    15. int num = 0;
    16. char msg[LEN] = {0};
    17. sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    18. if (sockfd < 0)
    19. {
    20. perror("socket():Create socket fails!\n");
    21. exit(1);
    22. }
    23. memset(&client_socket, 0, sizeof(client_socket));
    24. client_socket.sin_family = AF_INET;
    25. client_socket.sin_port = htons(1234);
    26. client_socket.sin_addr.s_addr = htonl(INADDR_ANY);
    27. int opt = SO_REUSEADDR;
    28. setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
    29. if(bind(sockfd,(struct sockaddr *)&client_socket,sizeof(struct sockaddr_in))<0)
    30. {
    31. perror("bind():bind fails!\n");
    32. exit(1);
    33. }
    34. while(1) //这里不使用while(1)依然可以持续接收
    35. {
    36. while((num = read(sockfd, msg, LEN)) > 0)
    37. {
    38. write(1,msg,num);
    39. }
    40. }
    41. close(sockfd);
    42. exit(0);
    43. }

  • 相关阅读:
    指挥棒:C++ 与运算符
    antv G6 开发踩坑记录
    Go开发工具GoLand V2022.2 来了——Go 工作区重大升级
    20220725 自动控制原理中的补偿器
    基于.NetCore开发博客项目 StarBlog - (4) markdown博客批量导入
    linux配置ssh无密码登录失败的一种原因
    软考考后常见问题详解~
    【小程序】-(小撒)
    二叉树学习笔记
    c++使用ifstream和ofstream报错:不允许使用不完整的类型
  • 原文地址:https://blog.csdn.net/wangjie36/article/details/125405561