• 接收端编程、UDP编程练习、wireshrak抓包工具、UDP包头


    我要成为嵌入式高手之3月6日Linux高编第十六天!!
    ————————————————————————————

    学习笔记

    接收端

    recvfrom

    #include
    #include socket.h>

    ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                            struct sockaddr *src_addr, socklen_t *addrlen);

    功能:从套接字中接收数据

    参数:

            sockfd:套接字文件描述符

            buf:存放数据空间首地址

            flags:属性,默认为0;

            src_addr:存放IP地址信息空间的首地址

            addrlen:存放接收到ip地址大小空间的首地址、

    返回值:成功返回实际接收字节数,失败返回-1;

    inet_ntoa

    功能:将二进制转换为字符串

    ntohs

    功能:将大端字节序转换为本地字节序

    1. #include "head.h"
    2. int main(void)
    3. {
    4. int sockfd = 0;
    5. struct sockaddr_in recvaddr;
    6. struct sockaddr_in tmpaddr;
    7. char tmpbuff[1024] = {0};
    8. ssize_t nsize = 0;
    9. ssize_t nsize1 = 0;
    10. char recvbuff[1024] = {0};
    11. socklen_t recvbufflen;
    12. recvbufflen = sizeof(tmpaddr);
    13. fgets(tmpbuff, sizeof(tmpbuff), stdin);
    14. // while (1)
    15. {
    16. /*创建用来通信的UDP套接字*/
    17. sockfd = socket(AF_INET, SOCK_DGRAM, 0);//通信使用的协议族(AF_INET是IPv4协议族),套接字类型:数据报套接字;默认0
    18. if (-1 == sockfd)
    19. {
    20. perror("fail to socket");
    21. return -1;
    22. }
    23. /*对接收方地址赋值*/
    24. recvaddr.sin_family = AF_INET;
    25. recvaddr.sin_port = htons(50001);//本地字节序转换为网络的大端字节序
    26. recvaddr.sin_addr.s_addr = inet_addr("192.168.1.101");//函数接口inet_addr将字符串的ip地址转换为内存当中的IP地址
    27. //前面是ip地址转换为32位之后的变量名
    28. /*发送信息*/
    29. nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
    30. //0为发送的属性,默认为0,发送到哪里(那个空间的首地址),那个地方的空间大小
    31. if (-1 == nsize)
    32. {
    33. perror("fail to sendto");
    34. return -1;
    35. }
    36. //printf("成功发送%ld字节!\n", nsize);
    37. /*接收信息*/
    38. nsize1 = recvfrom(sockfd, recvbuff, sizeof(recvbuff), 0, (struct sockaddr *)&tmpaddr, &recvbufflen);
    39. if (-1 == nsize1)
    40. {
    41. perror("fail to recvform");
    42. return -1;
    43. }
    44. printf("RECV ASCII FROM %s:%d %s\n", inet_ntoa(tmpaddr.sin_addr), ntohs(tmpaddr.sin_port), recvbuff);
    45. }
    46. close(sockfd);
    47. return 0;
    48. }

    bind

    #include          /* See NOTES */
    #include

    int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);

    功能:在套接字绑定一个IP地址和端口号

    参数:

            sockfd:套接字的文件描述符

            addr:绑定的IP地址空间的首地址

            addrlen:绑定IP地址的长度

    返回值:成功0,失败-1;

    UDP编程

    发端:

            socket -> sendto -> close

    收端:

            socket -> bind -> recvfrom -> close

    发端:

    1. #include "head.h"
    2. int main(void)
    3. {
    4. int sockfd = 0;
    5. char tmpbuff[1024] = {0};
    6. struct sockaddr_in myaddr;
    7. struct sockaddr_in recvaddr;
    8. ssize_t nsize = 0;
    9. int ret = 0;
    10. sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    11. if (-1 == sockfd)
    12. {
    13. perror("fail to socket");
    14. return -1;
    15. }
    16. myaddr.sin_family = AF_INET;
    17. myaddr.sin_port = htons(54321);
    18. myaddr.sin_addr.s_addr = inet_addr("192.168.1.172");
    19. ret = bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr));
    20. if (ret == -1)
    21. {
    22. perror("fail to bind");
    23. return -1;
    24. }
    25. fgets(tmpbuff, sizeof(tmpbuff), stdin);
    26. recvaddr.sin_family = AF_INET;
    27. recvaddr.sin_port = htons(30000);
    28. recvaddr.sin_addr.s_addr = inet_addr("192.168.1.167");
    29. nsize = sendto(sockfd, tmpbuff, strlen(tmpbuff), 0, (struct sockaddr *)&recvaddr, sizeof(recvaddr));
    30. if (-1 == nsize)
    31. {
    32. perror("fail to sendto");
    33. return -1;
    34. }
    35. printf("成功发送%ld字节数据\n", strlen(tmpbuff));
    36. close(sockfd);
    37. return 0;
    38. }

    收端:

    1. #include "head.h"
    2. int main(void)
    3. {
    4. int sockfd = 0;
    5. struct sockaddr_in myaddr;
    6. int ret = 0;
    7. size_t nsize = 0;
    8. char tmpbuff[1024] = {0};
    9. struct sockaddr_in sendaddr;
    10. socklen_t sendaddrlen;
    11. sendaddrlen = sizeof(sendaddr);
    12. sockfd = socket(AF_INET, SOCK_DGRAM, 0);
    13. if (-1 == sockfd)
    14. {
    15. perror("fail to sockfd");
    16. return -1;
    17. }
    18. myaddr.sin_family = AF_INET;
    19. myaddr.sin_port = htons(33333);
    20. myaddr.sin_addr.s_addr = inet_addr("192.168.1.172");
    21. ret = bind(sockfd, (struct sockaddr *)&myaddr, sizeof(myaddr));
    22. if (-1 == ret)
    23. {
    24. perror("fail to bind");
    25. return -1;
    26. }
    27. nsize = recvfrom(sockfd, tmpbuff, sizeof(tmpbuff), 0, (struct sockaddr *)&sendaddr, &sendaddrlen);
    28. if (-1 == nsize)
    29. {
    30. perror("fail to recvfrom");
    31. return -1;
    32. }
    33. printf("RECV ASCII FROM %s:%d %s", inet_ntoa(sendaddr.sin_addr), ntohs(sendaddr.sin_port), tmpbuff);
    34. return 0;
    35. }

    练习:

    编写程序实现两台主机间传输一个文件

    UPD中需要注意的点

    1、UDP是无连接的,发端退出收端没有任何影响

    2、UDP发送数据上限,最好不要超过1500字节

    3、UDP是不安全不可靠的,连续且快速的传输数据容易产生数据丢失

    wireshark

    抓包工具

    操作流程

            1、打开wireshrak

            2、选择抓取数据报的网卡(any)

            3、执行通信的代码

            4、停止通信

            5、设定过滤条件

                    ip.addr == IP地址

                    UDP\TCP\

                    udp.port == 端口号

    UDP包头

    长度:8字节

    源端口号(2字节)

    目标端口号(2字节)

    包长度(2字节)

    校验和(2字节)

  • 相关阅读:
    Footprint_Expert_2022-04_Pro 可以产生 cadence SPB16.6的封装
    基于双向LSTM模型进行电力需求预测(Matlab代码实现)
    2022强网杯WP
    vuex基础
    (附源码)mysql音乐播放器小程序 毕业设计 170900
    免费玩云上大数据--海汼部落实验室
    后端搜索条件
    [Rust笔记] 代码写明 Rust 中的泛型型变
    线上项目源码安全性处理方案
    多种方法解决leetcode经典题目-LCR 155. 将二叉搜索树转化为排序的双向链表, 同时弄透引用变更带来的bug
  • 原文地址:https://blog.csdn.net/weixin_71850179/article/details/136495445