UDP协议讲解

预备知识:

端口号port:

我们在正常网络通信时,实际上是进程在互相通信。

我们所有的网络通信的行为,本质上都是进程间通信。

对双方而言,1.先保证数据能到达自己的机器ip解决 2.找到指定的进程 端口号

ip地址用来标识互联网中唯一一台主机

端口号用来表示该指定的主机的进程的唯一性

所以ip+port={ip,port}互联网中唯一一个进程

{ip,port}我们把它叫做套接字,socket

**如何理解端口号?**uint16_t port

16位的数字,uint16_t port,用来标识主机的唯一的一个网络进程

为什么不直接用pid来表示网络中唯一一个进程

1.进程管理和网络管理进行解耦

2.port用来专门为网络通信

一个端口和一个进程进行关联?

一个进程可以和多个端口号关联,但是多个进程不能和一个端口号关联。

ip也可以对应多个端口号。

TCP和UDP

TCP协议:面向链接,面向字节流,可靠通信

UDP协议:面向数据报,无连接,不可靠通信

既然有了可靠通信,为什么又要设计不可靠通信

中性词,可靠通信,要得到保证就必须做更多的工作(复杂),不可靠通信,做更少的工作,很简单,丢包率也不会太高。他们之间只有不同没有好坏。

网络字节序列

在存储上我们有大端存储(大权值在低地址)和小端存储

也就是说不同机器的存储方式是不同的

我们在发数据,在内存中是以低地址到高地址发送,接收主机在内存中读取也是从低地址到高地址接收

网络规定达到网络的数据,都以大端发送,所有机器都知道数据是以大端发送的,所以小端机器就大端转化

到小端。因为主机的大小端是不一样的。

htonl:host to net int

因为port需要通过网络递送,所以得转成网络序列

socket:网路编程,socket是有很多类别的

1.unix socket :域间socket;同一台主机 的文件路径,在本主机进行通信

2.网络socket:ip+port:网络通信的文件

3.原始socket:编写一些网络工具

理论上以上三种类别都要有自己的一套接口

但是设计者只想用一套接口是一套通用的地址类型

Server服务器

创建套接字

return value;返回一个文件描述符

domain:网络通信的协议家族,也叫域

type:套接字的类型

protocol:tcp 或 udp

struct sockaddr_in local;

bzero(&lock,sizeof(local))

local.sin_family=AF_INET

local.sin_port=htons(_port)

local.sin_addr.s_addr=inet_addr(_ip)

​完成下列功能

1.四字节ip 2.网络序列

创建了socket我们要把他绑定,将它与socket关联

sockfd:socket返回的文件描述符

addr:传入sockaddr_un 或者 sockaddr_in

addrlen:结构体长度

服务器永远不退出,在Start中注定是一个死循环、

服务器接收

返回的是实际字节,len的期望收到的字节,flags默认为0(阻塞收消息)

后两个参数为输入输出型参数:给我们客户端client的信息 ip port,以后发消息就发给这个客户端

服务器发送

cpp 复制代码
#pragma once
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <arpa/inet.h>

#include "nocopy.hpp"
#include "Log.hpp"
#include "Comm.hpp"

using namespace std;
const uint16_t defaultport = 8888;
const int defaultsocketfd = -1;
const int buffsize = 1024;

class Udpserver : public nocopy
{
public:
  Udpserver(const uint16_t port = defaultport)
      : _port(port), _socketfd(defaultsocketfd)
  {
  }
  void Init()
  {
    // socket
    _socketfd = socket(AF_INET, SOCK_DGRAM, 0);
    if (_socketfd < 0)
    {
      lg.LogMessage(Fatal, "socket errr, %d : %s\n", errno, strerror(errno));
      cout << endl;
      exit(socketfderror);
    }
    lg.LogMessage(Info, "socketfd success \n");
    cout << endl;

    struct sockaddr_in local;
    bzero(&local, sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(_port);
    local.sin_addr.s_addr = INADDR_ANY;

    // bind
    int n = ::bind(_socketfd, (struct sockaddr *)&local, sizeof(local));

    if (n < 0)
    {
      lg.LogMessage(Fatal, "bind error,%d : %s\n", errno, strerror(errno));
      cout << endl;
      exit(binderror);
    }
    lg.LogMessage(Info, "bind success\n");
    cout << endl;
  }
  void Start()
  {
    for (;;)
    {
      struct sockaddr_in peer;
      socklen_t peerlen = sizeof(peer);
      char rbuff[1024];
      
      ssize_t n = recvfrom(_socketfd, rbuff, sizeof(rbuff - 1), 0, (struct sockaddr *)&peer, &peerlen);
      rbuff[n] = '\0';
      cout << "recv info:" << rbuff << endl;

      // if (n < 0)
      // {
      //   lg.LogMessage(Fatal, "recvfrom error,%d : %s\n", errno, strerror(errno));
      // }
      // rbuff[n]='\0';

      
      ssize_t sendn = sendto(_socketfd, rbuff, sizeof(buffsize), 0, (struct sockaddr *)&peer, peerlen);
      cout << "sendn success:" << rbuff << endl;
      if (n < 0)
      {
        lg.LogMessage(Fatal, "sendto error,%d : %s\n", errno, strerror(errno));
      }
    }
  }
  ~Udpserver() {}

private:
  // string _ip;
  uint16_t _port;
  int _socketfd;
};

netstat: 查看网络连接 -anup

Client客户端

创建套接字

client需不需要绑定,一定需要,但不需要显示绑定,client向服务器第一次发送信息时会自动绑定

为什么?

server的port众所周知是不可以随意改变的,client的port是随机端口,这是由于启动客户端的进程是很多

​的,

127.0.0.1:本地循环,通常用来网络cs的测试

我们想看到客户端的信息应该如何看到?

绑定云服务器地址失败?

云服务器的公网ip是虚拟的,无法直接bind,不推荐,更推荐本地任意ip的绑定方式

如何进行服务端的任意本地ip的绑定

IP=INADDR_ANY 实现动态绑定 0.0.0.0表示任意绑定

cpp 复制代码
#include <iostream>
#include <string>
#include <cerrno>
#include <cstring>
#include <unistd.h>

#include <sys/types.h>
#include <sys/socket.h>

#include <netinet/in.h>
#include <arpa/inet.h>
#include "Log.hpp"
#include "Comm.hpp"
const int defaultsrecbuff = 1024;
using namespace std;
void Usage(char *argv)
{
    cout << "Usage:" << argv << "+ServerIp+ServerPort" << endl;
}
int main(int argc, char *argv[])
{
    if (argc < 3)
    {
        Usage(argv[0]);
        cerr << "use client error" << endl;
        return Usage_Err;
    }
    // 创建套接字
    int socketfd = socket(AF_INET, SOCK_DGRAM, 0);
    // 填充server 发送信息
    string serverip = argv[1];
    uint16_t serverport = stoi(argv[2]);

    struct sockaddr_in server;
    bzero(&server, sizeof(server));
    server.sin_family = AF_INET;
    server.sin_port = htons(serverport);
    server.sin_addr.s_addr = inet_addr(serverip.c_str());
    while (true)
    {
        string buff;
        cout << "#Please enter:";
        getline(cin, buff);

        int n = sendto(socketfd, buff.c_str(), buff.size(), 0,
                       (const struct sockaddr *)&server, sizeof(server));
        if (n < 0)
        {
            cerr << "send error" << errno << strerror(errno);
            break;
        }
        else
        {
            // 接收信息
            struct sockaddr_in peer;
            socklen_t peerlen = sizeof(peer);
            char recbuff[defaultsrecbuff];
            int m = recvfrom(socketfd, recbuff, sizeof(recbuff)-1, 0,
                             (struct sockaddr *)&peer, &peerlen);
            if (m < 0)
            {
                cerr << "rec error" << errno << strerror(errno);
                 break;
            }
            else
            {
                recbuff[m]=0;
                cout << "#server say:" << recbuff << endl;
            }
        }
        
        
    }
    close(socketfd);
}

​​

相关推荐
熊的猫1 小时前
如何封装一个可取消的 HTTP 请求?
前端·javascript·vue.js·网络协议·http·webpack·node.js
AI原吾1 小时前
构建灵活、高效的HTTP/1.1应用:探索h11库
网络·python·网络协议·http·ai·h11
看山还是山,看水还是。1 小时前
Nginx 的 Http 模块介绍(中)
android·运维·网络·nginx·http
Tony聊跨境1 小时前
什么是 HTTP 代理?它如何工作?
网络·http·ip
licy__1 小时前
计算机网络期末考试试卷及答案
网络
码出钞能力1 小时前
UDP组播测试
网络·网络协议·udp
苏湘涵1 小时前
socket编程---UDP
linux·开发语言·网络·php·进程通信
清酒伴风(面试准备中......)1 小时前
计算机网络——开放系统互连参考模型
网络·计算机网络·1024程序员节
不甘平凡的蜜蜂1 小时前
第三十三篇:TCP协议如何避免/减少网络拥塞,TCP系列八
运维·网络·网络协议·tcp/ip·计算机网络·智能路由器