Linux socket 编程 UDP

news2024/9/20 14:46:52

套接字:操作系统向上层提供的用于实现网络通信的统称

网络通信其实本质上就是两台主机之间的通信其中一段是客户端,另一端是服务器

        客户端:用户的一端,客户端是主动发出请求的一端

        服务端:针对用户请求提供服务的一端,服务器是被动接收的一端

传输层协议:TCP UDP

        TCP :传输控制协议,面向连接,可靠传输,面向字节流

        应用于安全性要求大于实时性要求的场景 例如文件传输

        UDP:用户数据包协议,无连接,不可靠,面向数据报

        应用于对实时性要求大于安全性要求的场景 例如视频音频

UDP通信程序编写:

客户端:

        1.创建套接字

        2.为套接字绑定地址信息

        客户端不推荐绑定指定地址

                1.绑定之后,程序只能在启动一个

                2.客户端并不需要固定使用某个地址

        3.向服务器发送数据

                发送数据之前若socket没有绑定指定的地址信息,系统会选择合适的地址信息进行绑定

        4.接受数据

        5.关闭套接字

服务器

        1.创建套接字

                在内核创建socket 结构体,将进程跟网卡关联起来

        2.为套接字绑定指定地址信息

                给创建套接字socket结构体描述源端地址信息

                1.告诉系统,网卡收到哪个数据应该交给我

                2.当发送数据的时候使用绑定的地址信息作为源端地址信息

        3.接受数据

                从socket的接受缓冲区取出数据

        4.发送数据

                把要发送的数据放到发送缓冲区

        5.关闭套接字

UDP要用到的套接字接口介绍

socket();

函数原型:int socket(int domain, int type, int protocol);

参数介绍:

domain:地址域类型  ,指明使用的协议族。常用的协议族有AF_INET、AF_INET6,协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号(16位的)的组合

type:指明socket类型 SOCK_STREAM面向连接,面向字节流,可靠传输。TCP类型

SOCK_DGRAM,无连接,面向数据报,不可靠传输。UDP类型

protocol:协议类型 0是由系统自动选择的 IPRPROTO_TCP,IPRPROTO_UDP

返回值:成功返回套接字描述符,失败返回-1

bind ();

函数原型:int bind (int sockefd , const struct socketaddr * addr , socetlen_t addrlen);

参数介绍:

socketfd:socket();函数返回的描述符将socket绑定到指定的IP和端口上面,当socket返回描述符时,只是存在于其协议族中并没有实际分配协议地址。

addr:要绑定的地址信息 ipv4 是struct sockaddr_in     ipv6 是struct sockaddr_in6

addrler:地址信息长度,通常设置为sizeof(struct sockaddr)。

struct socketaddr_in

{

    sin_family;

    sin_port;

    sin_addr.s_addr;

}

返回值 0是成功 -1代表出错

sendto();

函数原型:sszie_t(int socketfd ,const void *buf,  size_t. len ,int flags,const struct sockaddr*dest_addr , socklen_t addrlen );

参数介绍:

socketfd:发送套接字的描述符 因为是用于非可靠链接UDP的数据发送,不用先建立连接,只需要给出目的协议地址就好了。

buf:要发送的数据空间首地址,因为UDP没有真正的发送缓冲区,因为是不可靠链接,不必保存应用里面的数据拷贝,因为应用进程中的数据沿协议向下传递的过程中,会以某种形式拷贝到内核缓冲区,当数据链路层把数据发出去的时候,内核缓冲区就会把数据删除,所以他不需要一个发送缓冲区

len:要发送的数据长度

flag:选项标志 0 默认为阻塞发送

dest_addr:对端地址信息

addrlen:地址信息长度

返回值:返回成功是实际发送的数据字节长度;失败返回-1;

recvfrom();

函数原型:ssize_t(int sockfd , void *buf , size_t len, int flags, struct sockaddr * src_addr , socklen_t * addrlen);

参数介绍:

sockfd:套接字描述符

buf:一块空间的首地址,用于存放从内核获取到的数据

len:要获取的数据长度

flag:默认0-阻塞接受

src_addr:当前接受的数据的发送方的地址信息

*addrlen:这是一个输入输出型参数,指定想要多长地址,返回实际长度

返回值:成功返回实际接收到的数据长度,失败返回-1;

函数实现

服务器

udp_srv.c

#include<stdio.h>
#include<unistd.h>
#include<string.h>
#include<netinet/in.h>//struct sockaddr_in 结构
#include<stdlib.h>
#include<arpa/inet.h>//字节序转换接口文件
#include<sys/socket.h>//socket接口文件

int main()
{
  //实现udp 服务器
  //创建套接字
  int sockfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
  if(sockfd < 0)
  {
    perror("socket error !");
    return -1;
  }

  //绑定地址信息bind
  struct sockaddr_in addr;
  addr.sin_family = AF_INET;
  addr.sin_port = htons(9090);
  addr.sin_addr.s_addr = inet_addr("10.0.8.12");

  socklen_t len = sizeof(struct sockaddr_in);
  int ret = bind(sockfd,(struct sockaddr* ) &addr ,len );
  if(ret < 0){
    close(sockfd);
    perror("bind error !");
    return -1;
  }
  while (1){
    //接受数据
    char buf[1024] = {0};
    struct sockaddr_in cliaddr;
    ret = recvfrom(sockfd,buf,1023,0,(struct sockaddr *) &cliaddr,&len);
    if(ret < 0){
      perror("recvfrom error !"); 
      close(sockfd);
      return -1;
    }
    printf("客户端: %s : %d 说: %s \n",inet_ntoa(cliaddr.sin_addr),ntohs(cliaddr.sin_port),buf);
    
    //发送数据
    printf("服务器: ");
    fflush(stdout);
    char data [1024] = {0};
    fgets(data,1023,stdin);
    ret = sendto(sockfd,data,strlen(data),0,(struct sockaddr*)&cliaddr,len);
    if(ret < 0){
      perror("sento error !");
      close (sockfd);
      return -1;
    }
  }
  // 关闭套接字
  close(sockfd);
  return 0;
}

udp_scoket.h

//封装一个udpsocket类
//通过实例化对象来调用成员函数完成客户端服务器搭建
#include<iostream>
#include<string>
#include<netinet/in.h>
#include<unistd.h>
#include<arpa/inet.h>
#include<sys/socket.h>
using namespace std;
class UdpSocket{
     private:
       int _sockfd;
     public:
       UdpSocket():_sockfd(-1){}
       ~UdpSocket()
       {
         if(_sockfd != -1)
         {
           close(_sockfd);
         }
       }
       bool Socket(){
         _sockfd = socket(AF_INET,SOCK_DGRAM,IPPROTO_UDP);
         if(_sockfd < 0)
         {
           perror("socket error !");
           return false;
         }
         return true;
       }
       bool Bind(const string &ip,uint16_t port){
         struct sockaddr_in addr;
         addr.sin_family = AF_INET;
         addr.sin_port = htons(port);
         addr.sin_addr.s_addr = inet_addr(ip.c_str());
         socklen_t len = sizeof(struct sockaddr_in);
         int ret;
         ret = bind(_sockfd,(struct sockaddr*)&addr,len);
         if(ret < 0)
         {
          perror("bind error !");
          return false;
         }
         return true;
       }

       bool Send(const string &data,const string &ip,uint16_t port){
         struct sockaddr_in addr;
         addr.sin_family = AF_INET;
         addr.sin_port = htons(port);
         addr.sin_addr.s_addr = inet_addr(ip.c_str());
         socklen_t len = sizeof(struct sockaddr_in);
         int ret;
         ret = sendto(_sockfd,data.c_str(),data.size(),0,(struct sockaddr*) &addr,len);
         if(ret < 0)
         {
           perror("sendto error");
           return false;
         }
         return true;
       }

       bool Recv(string *buf, string *ip = NULL,uint16_t *port = NULL)
       {
         struct sockaddr_in addr;
         socklen_t len = sizeof(struct sockaddr_in);
         char temp [4096] = {0};
         int ret;
         ret = recvfrom(_sockfd,temp,4096,0,(struct sockaddr *)&addr,&len);
         if(ret < 0){
           perror ("recvfrom error !");
           return false;
         }
         if(ip != NULL)
         {
           *ip = inet_ntoa(addr.sin_addr);
         }
         if(port != NULL){
           *port = ntohs(addr.sin_port);
         }
         *buf = temp;
         return true;
       }

       bool Close()
       {
         if(_sockfd != -1)
         {
           close(_sockfd);
         }
         return true;
       }
};

udp_cli.cpp

#include"udp_socket.hpp"
using namespace std;

#define CHECK_RES(q) if((q)==false) {return -1;}
int main(int argc,char *argv[])
{
      if(argc != 3){
        cout<< "Usage : ./udp_cli 10.0.8.12 9090" << endl;
        cout << "Server Address !" << endl;
        return -1;
      }
      string srv_ip = argv[1];
      int srv_port = stoi(argv[2]);
      UdpSocket sock;

      CHECK_RES(sock.Socket());

      while(1)
      {
        cout << "客户端 : " ;
        fflush(stdout);
        string buf;
        cin >> buf;

        CHECK_RES(sock.Send(buf,srv_ip,srv_port));

        buf.clear();
        CHECK_RES(sock.Recv(&buf));

        cout << "服务器 : " << buf << endl;
      }
      CHECK_RES(sock.Close());
      return 0;
}

 

 

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/2254.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

Linux 进程控制

&#x1f9d1;‍&#x1f4bb;进程控制 &#x1f9d1;‍&#x1f4bb; 文章目录&#x1f9d1;‍&#x1f4bb;进程控制 &#x1f9d1;‍&#x1f4bb;一、进程创建1. fork函数2. fork常规用法3. fork创建子进程操作系统都做了什么&#xff1f;4. 写时拷贝5. 父子进程代码的共享…

String(二)————迭代器及相关接口使用

目录 string构造接口&#xff08;Construct string object&#xff09; string的元素访问&#xff08;读写&#xff09; 迭代器 string构造接口&#xff08;Construct string object&#xff09; string相比于C语言的字符数组要好用的多&#xff0c;无论是在初始化还是在读写…

排序5:直接选择排序

目录 排序思想&#xff1a; 演示图&#xff1a; 代码实现 总结&#xff1a; 排序思想&#xff1a; 在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素 若它不是这组元素中的最后一个(第一个)元素&#xff0c;则将它与这组元素中的最后一个&#xff08;第一个…

SpringMVC---->自我实现底层机制(吃透springMVC)

目录 配套代码在资源中&#xff08;免费&#xff09; maven环境搭配 注解注入的规范&#xff1a; 一.开发HongDisptcherServlet前端控制器 1.说明&#xff1a; 2.配置web.xml文件 3.检查前期工作是否成功 二.完成客户端/浏览器请求控制层 1.创建 自己的 Controller 和…

【HTML+CSS+JS】模仿QQ登录界面

目录前言简介布局思路相关代码颜色渐变动画头像表单区域JS相关总结前言 学了HTML、CSS和JS有了一个月了&#xff0c;JS还未学完&#xff0c;偷懒写一个小项目&#xff0c;用了一个下午&#xff0c;顺便巩固一下所学知识。&#xff08;内容比较简陋&#xff0c;适合新手&#x…

基于火鹰优化算法的函数寻优算法

文章目录一、理论基础1、火鹰优化算法2、FHO算法伪代码二、仿真实验与结果分析三、参考文献一、理论基础 1、火鹰优化算法 文献[1]提出了火鹰优化算法(Fire Hawk Optimizer, FHO)作为一种新的元启发式算法&#xff0c;该算法基于啸鸢、麻鹰和褐隼的觅食行为&#xff0c;这些鸟…

【网络原理】网络编程Socket套接字基础知识汇总

目录 1.网络初始&#xff1a; 2.网络编程&#xff1a; 3.UDP数据报套接字&#xff1a; 4.TCP流套接字&#xff1a; 1.网络初始&#xff1a; 局域网&#xff08;LAN&#xff09;广域网&#xff08;WAN&#xff09;IP地址用于定位主机的网络地址。端口号可以标识主机中发送数…

数据结构六:堆

前言&#xff1a;上一篇我们讲了二叉树&#xff0c;你知道吗&#xff1f;堆的底层是一棵完全二叉树。这样说会不会就会觉得熟悉了。 目录 1.堆的概念及存储方式 2&#xff1a;堆的创建 2.1:向下调整 3.堆的插入和删除 3.1&#xff1a;堆的插入 3.2&#xff1a;堆的删除 …

基于Web的商城后台管理系统的设计与实现

&#x1f389;精彩专栏推荐 &#x1f4ad;文末获取联系 ✍️ 作者简介: 一个热爱把逻辑思维转变为代码的技术博主 &#x1f482; 作者主页: 【主页——&#x1f680;获取更多优质源码】 &#x1f393; web前端期末大作业&#xff1a; 【&#x1f4da;毕设项目精品实战案例 (10…

Oracle和MySQL查询所有的表信息和字段信息

Oracle和MySQL查询所有的表信息和字段信息1. MySQL1.1 查询表1.2 查询字段1.2.1 方式1->SHOW FULL COLUMNS1.2.2 方式2->information_schema.COLUMNS1.3 查表和字段1.4 查表和字段-->转程Oracle需要的数据类型2. Oracle2.1 查表和字段的单表查询2.2 整理查表和字段的s…

超详细的JUnit单元测试介绍

前言 本文为JUnit单元测试相关知识&#xff0c;下边将对JUnit单元测试概念&#xff0c;JUnit优点&#xff0c;JUnit安装与使用&#xff0c;JUnit运行流程与常用注解&#xff0c;JUnit测试套件使用及参数化设置&#xff0c;JUnit断言等进行详尽介绍~ &#x1f4cc;博主主页&…

大数据Hadoop之——Apache Hudi 与 Presto/Trino集成

文章目录一、概述二、Trino 环境部署1&#xff09;安装JDK2&#xff09;安装python3&#xff09;安装Trino1、下载解压并配置环境变量2、修改配置3、启动服务4、测试验证三、在Hive中创建表关联Hudi表1&#xff09;添加jar包2&#xff09;创建库表关联Hudi四、Hudi 与 Trino集成…

SpringCloud Alibaba系列 Sentinel(三)

高并发下的微服务容错方案&#xff1f; 限流、熔断、降级 1&#xff1a;限流 在高并发系统中一定要用&#xff0c;高并发的所有请求进来&#xff0c;不是让每个请求都打到后台集群的&#xff0c;后台集群有它的消费能力&#xff0c;应该在它消费能力之内放行请求&#xff0c;…

Hadoop HA集群全是standBy解决办法

文章目录原理解决方案原理 hadoop集群配置HA后&#xff0c;会存在多个namenode&#xff0c;但是同一时间仅有一台NN为Active的状态&#xff0c;其他NN都是StandBy的状态。 上图是hadoop集群配置HA的原理图&#xff0c;从上图我们可以看到多个NN的状态切换&#xff0c;是依靠Z…

linux命令与makefile学习

linux命令与makefile学习文件权限通配符*常用命令makefilegcc与g区别&#xff1a;Linux上有一句话&#xff1a;一切皆文件 普通文件 “-” 目录文件 “d” &#xff08;directory&#xff09; 管道文件 “p” &#xff08;piping&#xff09; 链接文件“l” &#xff08;li…

SAP FICO银行账户余额查询表开发说明书(包括开发源代码、测试样例及FS)

程序说明 满足财务银行账户余额查询明细的需求; 支持财务实时查看银行余额数据。 筛选界面 序号 栏位标题 字段类型 是否必须 是否为范围

【pwn】2022 祥云杯 部分wp

【pwn】2022 祥云杯 部分wp 前言 又是一年的祥云杯&#xff0c;相比去年我啥也不会写&#xff0c;今年起码写了几个签到… 又被队友带飞咯 protool Google的Protobuf&#xff0c;参考学习连接 https://bbs.pediy.com/thread-270004.htm 发现了栈溢出&#xff0c;protobuf…

Unity技术手册-UGUI零基础详细教程-Toggle切换

往期文章分享点击跳转>《导航贴》- Unity手册&#xff0c;系统实战学习点击跳转>《导航贴》- Android手册&#xff0c;重温移动开发 本文约3千字&#xff0c;新手阅读需要7分钟&#xff0c;复习需要2分钟 【收藏随时查阅不再迷路】 &#x1f449;关于作者 众所周知&#…

2.6 Python 基本数据类型

1. 数据类型 类型是变量所指的内存中对象的类型. 内置的type()函数可以用来查询变量所指的对象类型。Python 3中有六个标准的数据类型: Numbers(数字), String(字符串), List(列表), Tuple(元组), Sets(集合), Dictionary(字典).2. Numbers 数字型 Python 有三种数字类型 in…

SpringMVC基本配置

小常规 springmvc的处理器对应的bean必须按照规范格式开发&#xff0c;为避免加入无效的bean可通过bean加载过滤器进行包含设定或排除设定&#xff0c;表现层bean标注通常设定为Controller在此发现图片没有加载出来回到程序去分析当发起一个请求以后DispatcherServlet配置拦截所…