IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> UDP实现简单通讯(夕佳佳) -> 正文阅读

[网络协议]UDP实现简单通讯(夕佳佳)

1、概念

  1. 网络通信如何识别通讯双方:(五元组) 一个本机IP对应自己的电脑,远程IP对应一个别人的电脑; 以及电脑有多个运行的程序,用端口号区分不同的程序

    并且使用协议名最终确定

  2. INADDR_ANY 泛指本机IP(即0.0.0.0)

    #define INADDR_ANY ? ? ? ? ? ?  (ULONG)0x00000000

  3. 客户端和服务端的地址设置: 地址都是表明自己的,所以服务端必然是本机,客户端就是其他人电脑对应的IP

2、实现流程图

借用丙佬的图,顺便附上链接基于 UDP 的套接字通信 | 爱编程的大丙 (subingwen.cn)

(本质上我自己没有完成互相通讯,只有一个单向传播嘤嘤嘤)

3、代码分段解读(其实算是分功能)

  1. /*初始化WSA*/
    ?
    WSADATA data; ? ? ? ? ?//创建对象
    int error = WSAStartup(MAKEWORD(2, 2), &data);//WSA 是windows socket api,这里创建一个对象?可以回来补充!;MAKEWORD(2,2)是使用version2.2的套接字
    if (error != 0)
    {
     ? ?printf("error\n");
     ? ?return 1;
    }
    //这里检查版本对不对,高字节是主版本,低字节是副版本
    if (HIBYTE(data.wVersion) != 2 || LOBYTE(data.wVersion) != 2)
    {
     ? ?WSACleanup();
     ? ?printf("version wrong\n");
     ? ?return 0;
    }

  2. /*实例化SOCKET*/
    ?
    SOCKET client_sock = socket(AF_INET, SOCK_DGRAM, 0);
    ?
    //第一个是地址类型;第二个是套接字类型;第三个是要使用的通讯协议
    //其他参数见官方doc
    //https://docs.microsoft.com/en-us/windows/win32/api/winsock2/nf-winsock2-socket

  3. /*实例化SOCKADDR_IN*/
    ?
    SOCKADDR_IN server_address;
    ?
    //三个主要属性:1.sin_addr 表示socket收发地址,这是一个结构体;常见的有
    server_address.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
    //或者↓这下面的是wsa2.h的表达方式
    inet_pton(AF_INET, "10.136.122.138", &server_address.sin_addr.S_un.S_addr);
    // ? ? ? ? ?  2.sin_family  如果用socket编程,似乎只能用AF_INET
    // ? ? ? ? ?  3.sin_port ? 表示该程序的端口号(自己找一个空闲的端口号),有需要对应htons函数
    //具体举个例子
    ?
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(6666);


  4. /*绑定套接字和地址*/
    bind(server_sock, (SOCKADDR*)&server_address, sizeof(SOCKADDR));

  5. /*初始化一些用于收发的存储量*/
    int len = sizeof(SOCKADDR);
    char ?send_buffer[100] = "abbbbb";

  6. 最后简单介绍一下sendtorecvfrom的用法 (1)函数原型

    int WSAAPI sendto(
      [in] SOCKET ? ? ? ? s,
      [in] const char ? ? *buf,
      [in] int ? ? ? ? ? ?len,
      [in] int ? ? ? ? ? ?flags,
      [in] const sockaddr *to,
      [in] int ? ? ? ? ? ?tolen
    );
    ?
    //举个例子
    ?
    sendto(client_sock, send_buffer, strlen(send_buffer) + 1, 0, (SOCKADDR*)&server_address, len);
    //这个是客户端发给服务端的句子;第一项就是使用者端的套接字
    // ? ? ? ? ? ? ? ? ? ? ? ? 第二项目是发送的字符串
    // ? ? ? ? ? ? ? ? ? ? ? ? 第三项是这个字符串的长度
    // ? ? ? ? ? ? ? ? ? ? ? ? 第四项俺也不太会,一般默认0
    // ? ? ? ? ? ? ? ? ? ? ? ? 第五项是发送给的东西的地址,传参传sockaddr结构体的指针
    // ? ? ? ? ? ? ? ? ? ? ? ? 第六项是这个sockaddr的大小;int len = sizeof(SOCKADDR);
    int WSAAPI recvfrom(
      [in] ? ? ? ? ? ? ? ?SOCKET ? s,
      [out] ? ? ? ? ? ? ? char ? ? *buf,
      [in] ? ? ? ? ? ? ? ?int ? ? ?len,
      [in] ? ? ? ? ? ? ? ?int ? ? ?flags,
      [out] ? ? ? ? ? ? ? sockaddr *from,
      [in, out, optional] int ? ? ?*fromlen
    );
    ?
    //举个例子
    ?
    recvfrom(server_sock, recieve_buffer, sizeof(recieve_buffer), 0, (SOCKADDR*)&client_address, &len);
    //这个是服务端接受客户端发送来的信息的例子;第一项是使用者的套接字
    // ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第二项是存信息的数组
    // ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第三项是这个数组长度
    // ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第四项同上,默认0吧
    // ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第五项是数据来源的地址,传的同样是sockaddr的指针
    // ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? 第六项同前

4、实现代码

(1)功能提醒:就是简单的客户端发,服务端收;这种最基础的都大同小异,可能得掌握bind、端口等具体含义与作用后拓展会更好(这只小菜狗想试着做个狼人杀系统,但是可能大概率寄)

(2)客户端

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <string.h>
?
#pragma comment(lib, "Ws2_32.lib")
?
int main(void)
{
    WSADATA data;
    int error = WSAStartup(MAKEWORD(2, 2), &data);
    if (error != 0)
    {
        printf("error\n");
        return 1;
    }
    if (HIBYTE(data.wVersion) != 2 || LOBYTE(data.wVersion) != 2)
    {
        WSACleanup();
        printf("version wrong?\n");
        return 0;
    }
?
    SOCKET client_sock = socket(AF_INET, SOCK_DGRAM, 0);
?
    //这里考虑去掉,晚上回来试试
    SOCKADDR_IN client_address;
    inet_pton(AF_INET, "10.136.210.98", &client_address.sin_addr.S_un.S_addr);//这里记得换一下,变成其他电脑的ip
    client_address.sin_family = AF_INET;
    client_address.sin_port = htons(6666);
    //去掉↑
?
    //手动加
    SOCKADDR_IN server_address;
    inet_pton(AF_INET, "我自己电脑(服务端)的ip", &server_address.sin_addr.S_un.S_addr);
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(6666);
?
?
    int len = sizeof(SOCKADDR);
    char ?send_buffer[100] = "abbbbb";
?
    printf("Connection established,send \'#\' to disconnect.\n");
?
    while (1)
    {
        puts("enter sth to send:");
        gets_s(send_buffer);
?
?
        sendto(client_sock, send_buffer, strlen(send_buffer) + 1, 0, (SOCKADDR*)&server_address, len);
?
?
    }
    closesocket(client_sock);
    WSACleanup();
    return 0;
}

(3)服务端

#include <winsock2.h>
#include <ws2tcpip.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
?
#pragma comment(lib, "Ws2_32.lib")
?
int main(void)
{
    WSADATA data;
    int error = WSAStartup(MAKEWORD(2, 2), &data);
    if (error != 0)
    {
        printf("error\n");
        return 1;
    }
    if (HIBYTE(data.wVersion) != 2 || LOBYTE(data.wVersion) != 2)
    {
        WSACleanup();
        printf("version wrong?\n");
        return 0;
    }
?
    SOCKET server_sock = socket(AF_INET, SOCK_DGRAM, 0);
?
    SOCKADDR_IN server_address;
    server_address.sin_addr.S_un.S_addr = inet_addr("我自己电脑的ip");
    server_address.sin_family = AF_INET;
    server_address.sin_port = htons(6666);
?
    int flag = bind(server_sock, (SOCKADDR*)&server_address, sizeof(SOCKADDR));
    if (flag == -1)
        puts("eeee");
    SOCKADDR_IN client_address;
    //这里加进去的
    client_address.sin_addr.S_un.S_addr = inet_addr("10.135.7.112");//这里记得换一下,变成其他电脑的ip
    client_address.sin_family = AF_INET;
    client_address.sin_port = htons(6666);
    //这里加入
    int len = sizeof(client_address);
    char recieve_buffer[100], send_buffer[100] = "abbbbbbbbbbbbbbbbbb", tmp_buffer[30];
?
    printf("Connection established,send \'#\' to disconnect.\n");
?
    while (1)
    {
        recvfrom(server_sock, recieve_buffer, sizeof(recieve_buffer), 0, (SOCKADDR*)&client_address, &len);
        puts("recieved\n");
        printf("%s\n", recieve_buffer); 
    }
?
    closesocket(server_sock);
    WSACleanup();
?
    return 0;
}
  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2022-03-30 19:06:09  更:2022-03-30 19:06:17 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/26 5:20:56-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码