UDP网络编程

这篇具有很好参考价值的文章主要介绍了UDP网络编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

一、UDP的概念

1.1、UDP——面向无连接(无连接,是因为UDP里有了对方的地址,直接发就好)

特点:

          1、邮件系统服务模式的抽象
          2、每个分组都携带完整的目的地址
          3、不能保证分组的先后顺序
          4、不进行分组出错的恢复和重传
          5、不保证数据传输的可靠性 

1.2、UDP协议

 面向无连接的用户数据报协议,在传输数据前不需要先建立连接;目地主机的运输层收到 UDP 报文后,不需要给出任何确认。

UDP 其它特点
                 1、相比 TCP 速度稍快些
                 2、简单的请求/应答应用程序可以使用 UDP
                 3、对于海量数据传输不应该使用 UDP
                 4、广播和多播应用必须使用 UDP

UDP 应用
                DNS(域名解析)、NFS(网络文件系统)、RTP(流媒体)等

二、网络编程接口socket

2.1、socket 作用

            提供不同主机上的进程之间的通信

2.2、socket 特点

1、socket 也称“套接字”
2、是一种文件描述符,代表了一个通信管道的一个端点
3、类似对文件的操作一样,可以使用 read、write、close 等函数对 socket 套接字进行网络  数据的收取和发送等操作。
4、得到 socket 套接字(描述符)的方法调用 socket()

三、UDP编程C/S架构

udp编程,计算机网络,udp,网络协议

四、创建 socket 套接字

头文件:

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

函数:

            int socket(int domain, int type, int protocol);
功能:

           创建一个套接字,返回一个文件描述符
参数:
            domain:通信域,协议族
                           AF_UNIX     本地通信
                           AF_INET     ipv4网络协议(常用)
                           AF_INET6   ipv6网络协议
                           AF_PACKET 底层接口

             type:套接字的类型 
                          SOCK_STREAM 流式套接字(TCP)
                          SOCK_DGRAM 数据报套接字(UDP)本章学习UDP
                          SOCK_RAW 原始套接字(用于链路层)
             protocol:附加协议,如果不需要,则设置为0
 返回值:
               成功:文件描述符
               失败:‐1

 特点:

           创建套接字时,系统不会分配端口
           创建的套接字默认属性是主动的,即主动发起服务的请求;当作为服务器时,往往需要修改为被动的。

五、创建UDP套接字

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

 int main(int argc, char const *argv[])
 {
  //使用socket函数创建套接字
  //创建一个用于UDP网络编程的套接字
   int sockfd;
   if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == ‐1)
 {
    perror("fail to socket");
    exit(1);
   }

    printf("sockfd = %d\n", sockfd);

    return 0;
 }

运行结果

sockfd = 3 

六、UDP编程——发送、绑定、接收数据

6.1、发送数据——sendto()函数

头文件

             #include <sys/types.h>
             #include <sys/socket.h>
函数:

            ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,const struct sockaddr *dest_addr, socklen_t addrlen);
功能:

            发送数据
参数:
                sockfd:文件描述符,socket的返回值
                     buf:要发送的数据
                     len:buf的长度
                  flags:标志位
                               0 阻塞   (基本都设置为0)
                              MSG_DONTWAIT 非阻塞
           dest_addr:目的网络信息结构体(需要自己指定要给谁发送)
               addrlen:dest_addr的长度
返回值:
                   成功:发送的字节数
                   失败:‐1

此函数,重点 :const struct sockaddr *dest_addr   如何构建

通过man手册查询:sockaddr通用结构体

头文件:

                 #include <netinet/in.h>

函数结构体:
                      struct sockaddr
                   {
                       sa_family_t sa_family;   // 2字节
                       char sa_data[14]           //14字节
                    };

 但是,在网络编程中经常使用的结构体sockaddr_in

6.2、sockaddr_in(重点)

头文件:

                #include <netinet/in.h>

 函数结构体:

 
 struct sockaddr_in
    {
        sa_family_t sin_family;            //协议族 2字节
        in_port_t sin_port;                    //端口号 2字节
        struct in_addr sin_addr;       //ip地址 4字节
        char sin_zero[8]                       //填充,不起什么作用 8字节
          };

   struct in_addr
      {
      in_addr_t s_addr;                       //ip地址 4字节
             };

 6.2.1、sockaddr_in使用说明

           在定义源地址和目的地址结构的时候,选用struct sockaddr_in;
  例:
           struct sockaddr_in my_addr;
          当调用编程接口函数,且该函数需要传入地址结构时需要用struct sockaddr进行强制转换
例:
         bind(sockfd,(struct sockaddr*)&my_addr,sizeof(my_addr));

七、向"网络调试助手"发送消息(作为服务器)

        设置网络调试助手(在windows下运行的软件)中的属性

udp编程,计算机网络,udp,网络协议
注意:ip地址不能随意设置,必须是当前windows的ip地址

 八、unbantu下客户端发送给windows下运行"网络调试助手"

#include<stdio.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include<stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<string.h>


#define N 128



int main(int argc, char **argv)
{
	if(argc<3)
  {
	  fprintf(stderr,"%s ip post",argv[0]);
	   exit(1);
	   }

	int sockfd;

	if((sockfd=socket(AF_INET, SOCK_DGRAM,0))==-1)
	{
	   perror("fail to sockfd");
	   exit(1);
		
		}	
     
	printf("sockfd = %d \n",sockfd);
    
	struct sockaddr_in  myaddr;

	myaddr.sin_family=AF_INET;
	myaddr.sin_port =htons(atoi(argv[2]));
	myaddr.sin_addr.s_addr = inet_addr(argv[1]);
    
    socklen_t addrlen=sizeof(myaddr);
    
	char buf[N]="";

	while(1)
	{	
      fgets(buf,N,stdin);

  //    buf[strlen(buf)-1]='\0';   //有这句话,不会换行

      if(sendto(sockfd,buf,N,0,(struct sockaddr*)&myaddr,addrlen)==-1)
	{
		perror("sendto fail");
		exit(1);
		
		}	
  	
	   }
	close(sockfd);
	return 0;
	}

运行结果

 udp编程,计算机网络,udp,网络协议

九、unbantu作为服务器接收数据,网络调试助手作为客户端发送数据 

 9.1、服务器为客户端服务,因此需要有固定的ip和端口号——bind函数绑定

头文件:

            #include <sys/types.h>
            #include <sys/socket.h>
函数:

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

          将套接字与网络信息结构体绑定
参数:
           sockfd:文件描述符,socket的返回值
              addr:网络信息结构体
    struct sockaddr:通用结构体(一般不用
            使用网络信息结构体 sockaddr_in

结构体头文件

               #include <netinet/in.h>
 结构体函数

               struct sockaddr_in
               addrlen:addr的长度
 返回值:
               成功:0
               失败:‐1

 9.2、sockaddr_in使用说明

头文件:

                #include <netinet/in.h>

 函数结构体:

 
 struct sockaddr_in
    {
        sa_family_t sin_family;            //协议族 2字节
        in_port_t sin_port;                    //端口号 2字节
        struct in_addr sin_addr;       //ip地址 4字节
        char sin_zero[8]                       //填充,不起什么作用 8字节
          };

   struct in_addr
      {
      in_addr_t s_addr;                       //ip地址 4字节
             };

 9.3、bind的绑定示例

#include<stdio.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include<stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>


int main(int argc , char **argv[])
{
	
	int sockfd;

    if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
	{
		perror("fail to sockfd");
		exit(1);
		
		}
     printf("sockfd= %d\n",sockfd);

    //bind的函数	 
	struct sockaddr_in mysockaddr;

	mysockaddr.sin_family=AF_INET;
	mysockaddr.sin_port =htons(8080);
	mysockaddr.sin_addr.s_addr = inet_addr("10.152.203.29");
    
    socklen_t addrlen = sizeof(mysockaddr);

   	if(bind(sockfd,(struct sockaddr *)&mysockaddr,addrlen)==-1)
	{
		perror("fail to bind");
		exit(1);
		
		}
	
	}

补充知识:

                 inet_addr

头文件:

              #include <sys/socket.h>
              #include <netinet/in.h>
              #include <arpa/inet.h>
函数:
             in_addr_t    inet_addr(const char *cp);
 功能:

             将点分十进制ip地址转化为整形数据

              此转换的整形数据也是网络字节序
 参数:
              cp:点分十进制的IP地址
 返回值:
              成功:整形数据
 

 atoi函数(字符串转化成整数)

 头文件

                  #include<stdlib.h>
函数

               int atoi(const char *nptr);
功能
              把字符串转化为int类型
返回

             返回转换后的整型数。

端口号,在我们输入时候,是以字符串形式表达,而我们的结构sockaddr_in 接收的是 整形

因此需要:  atoi(端口号)     变为整形数。 

只是转为整形数,还不行,由于不同计算机之间通讯,需要转换自己的字节序为网络字节序

因此需要: htons(atoi(端口号));

十、接收到数据——recvfrom函数 

头文件

                  #include <sys/types.h>
                  #include <sys/socket.h>
函数
         ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,5 struct sockaddr *src_addr, socklen_t *addrlen);
功能:

            接收数据
参数:

               sockfd:文件描述符,socket的返回值
                    buf:保存接收的数据
                    len:buf的长度
                 flags:标志位
                                        0 阻塞(基本都设置0)
                                        MSG_DONTWAIT 非阻塞
                 src_addr:源的网络信息结构体(自动填充,定义变量传参即可

                 会自动接收对方的ip地址,和端口号,存放此结构体中
                 addrlen:src_addr的长度
 返回值:
               成功:接收的字节数
                失败:‐1

 10.1、recvfrom函数示例

#include<stdio.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include<stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define N 128

int main()
{
 char buf[N]="";

	 struct sockaddr_in recvfrom_addr;
     socklen_t recvfrom_addrlen = sizeof(recvfrom_addr);

     while(1)
{		 
     if(recvfrom(sockfd,buf,N,0,(struct sockaddr *)&recvfrom_addr,&recvfrom_addrlen)==-1)
		{
			
			perror("fail to recvfrom");
			exit(1);
			}

			
        printf("%s\n",buf);	
 }
  return 0;
}

十一、unbantu作为服务端 (代码示例)

#include<stdio.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include<stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>


#define N 128
int main(int argc , char *argv[])
{
    if(argc<3)
	{
	   	
	  fprintf(stderr, "%s ip port ",argv[0]);
	  exit(1);
		
		}	
  

	int sockfd;

    if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
	{
		perror("fail to sockfd");
		exit(1);
		
		}
     printf("sockfd= %d\n",sockfd);
	 
	struct sockaddr_in mysockaddr;

	mysockaddr.sin_family=AF_INET;
	mysockaddr.sin_port =htons(atoi(argv[2]));
	mysockaddr.sin_addr.s_addr = inet_addr(argv[1]);
    
    socklen_t addrlen = sizeof(mysockaddr);
       
    
   	if(bind(sockfd,(struct sockaddr*)&mysockaddr,addrlen)<0)
	{
		perror("fail to bind");
		exit(1);
		
		}
       
	 
	 char buf[N]="";
	 struct sockaddr_in recvfrom_addr;
     socklen_t recvfrom_addrlen = sizeof(recvfrom_addr);

     while(1)
{		 
     if(recvfrom(sockfd,buf,N,0,(struct sockaddr *)&recvfrom_addr,&recvfrom_addrlen)==-1)
		{
			
			perror("fail to recvfrom");
			exit(1);
			}

			
        printf("%s\n",buf);	
 }
  
	return 0;
	}

 运行结果

udp编程,计算机网络,udp,网络协议

 注意:当我们关掉unbantu服务端程序时,如果在运行同一个端口号,会遇到运行错误。需要换一个端口号才可以运行成功。

当我们发送信息时,先把发送的内容写进buf里,然后再传输给对方。当我们再继续发信息时,原先buf里面装的内容不会清除,如果发的信息多,能覆盖之前buf内容,则输出正常。如果发的信息少,不能覆盖原先的buf的内容,只覆盖前面几个数据,后面原先的数据,照常发送给对方。

十二、客户端发信息并能接收服务端回信息(更完善) 

12.1、客户端示例代码

#include<stdio.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include<stdlib.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<string.h>


#define N 128



int main(int argc, char **argv)
{
	if(argc<3)
  {
	  fprintf(stderr,"%s ip post",argv[0]);
	   exit(1);
	   }

	int sockfd;

	if((sockfd=socket(AF_INET, SOCK_DGRAM,0))==-1)
	{
	   perror("fail to sockfd");
	   exit(1);
		
		}	
     
	printf("sockfd = %d \n",sockfd);
    
	struct sockaddr_in  myaddr;

	myaddr.sin_family=AF_INET;
	myaddr.sin_port =htons(atoi(argv[2]));
	myaddr.sin_addr.s_addr = inet_addr(argv[1]);
    
    socklen_t addrlen=sizeof(myaddr);
    
	char buf[N]="";
	

	while(1)
	{
	  char context[50]="";	
      fgets(buf,N,stdin);

  //    buf[strlen(buf)-1]='\0';  

      if(sendto(sockfd,buf,N,0,(struct sockaddr*)&myaddr,addrlen)==-1)
	{
		perror("sendto fail");
		exit(1);
		
		}	
  	  
	 

      if(recvfrom(sockfd,context,sizeof(context),0,(struct sockaddr*)&myaddr,&addrlen)==-1)
	  {
		   perror("fail to recvfrom");
		   exit(1);
		   }
	  
	  printf("from server: %s\n", context);


	   }
	   close(sockfd);
	
	return 0;
	}

12.2、服务端示例代码

#include<stdio.h>
#include <sys/types.h>         
#include <sys/socket.h>
#include<stdlib.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include<string.h>

#define N 128
int main(int argc , char *argv[])
{
    if(argc<3)
	{
	   	
	  fprintf(stderr, "%s ip port ",argv[0]);
	  exit(1);
		
		}	
  

	int sockfd;

    if((sockfd=socket(AF_INET,SOCK_DGRAM,0))==-1)
	{
		perror("fail to sockfd");
		exit(1);
		
		}
     printf("sockfd= %d\n",sockfd);
	 
	struct sockaddr_in mysockaddr;

	mysockaddr.sin_family=AF_INET;
	mysockaddr.sin_port =htons(atoi(argv[2]));
	mysockaddr.sin_addr.s_addr = inet_addr(argv[1]);
    
    socklen_t addrlen = sizeof(mysockaddr);
       
    
   	if(bind(sockfd,(struct sockaddr*)&mysockaddr,addrlen)<0)
	{
		perror("fail to bind");
		exit(1);
		
		}
       
	
	 char buf[N]="";
	 struct sockaddr_in recvfrom_addr;
     socklen_t recvfrom_addrlen = sizeof(recvfrom_addr);

     while(1)
{		
         char text[50]=""; 
     if(recvfrom(sockfd,buf,N,0,(struct sockaddr *)&recvfrom_addr,&recvfrom_addrlen)==-1)
		{
			
			perror("fail to recvfrom");
			exit(1);
			}

          printf("ip:%s ,port:%d\n", inet_ntoa(recvfrom_addr.sin_addr), ntohs(recvfrom_addr.sin_port));	
          printf("%s\n",buf);

          strcat(text, " *_*");

         if(sendto(sockfd, text, sizeof(text), 0, (struct sockaddr *)&recvfrom_addr, addrlen) < 0)
           {
            perror("fail to sendto");
                exit(1);
                }
	
 }
    close(sockfd);
  
	return 0;
	}

 运行结果

udp编程,计算机网络,udp,网络协议

可以实现多并发 

 文章来源地址https://www.toymoban.com/news/detail-523106.html

到了这里,关于UDP网络编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【计算机网络】UDP协议概述

    UDP协议(User Datagram Protocol,用户数据报协议):面向无连接的协议,不保证可靠性,但是具有较低的延迟和更快的传输速度,常用于实时音视频传输、广播和多播等场景。 基于数据报文 :UDP把应用层提交给它的数据报文,添加上UDP首部后传输,每个UDP数据报的大小不能超过

    2024年02月06日
    浏览(54)
  • 【计算机网络篇】UDP协议

    ✅作者简介:大家好,我是小杨 📃个人主页:「小杨」的csdn博客 🐳希望大家多多支持🥰一起进步呀! UDP(User Datagram Protocol)是一种无连接的传输层协议,它提供了一种简单的、不可靠的数据传输服务。 UDP 提供了不面向连接的通信,且不对传送的数据报进行可靠的保证,

    2024年02月12日
    浏览(42)
  • 【计算机网络】UDP协议详解

    目录 前言       端口号的拓展 端口号范围划分 netstat pidof UDP协议 UDP协议端格式 UDP的特点 面向数据报 UDP的缓冲区 UDP使用注意事项 基于UDP的应用层协议     我们前面讲完了 http和https协议 ,它们都属于 应用层 ,按照TCP/IP五层模型,我们下一层该讲解 传输层 了。传输层又

    2024年02月09日
    浏览(70)
  • 【计算机网络】简易UDP网络小程序

    我们把服务封装成一个类,当我们定义出一个服务器对象后需要马上初始化服务器,而初始化服务区需要做的第一件事就是创建套接字。 创建套接字我们需要用到socket函数 参数说明: domain:创建套接字的域或者叫做协议家族,也就是套接字的类型。该参数就相当于 struct s

    2024年02月16日
    浏览(73)
  • 【计算机网络】UDP/TCP 协议

    端口号(Port)标识了一个主机上进行通信的不同的应用程序。在 TCP/IP 协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信(可以通过netstat -n查看)。 0 - 1023: 知名端口号,HTTP, FTP, SSH 等这些广为使用的应用层协议,它们的

    2024年03月14日
    浏览(63)
  • 【计算机网络】UDP/TCP协议

    我们先来看一张图; 在研究UDP前我们先来回答两个问题: 有效载荷如何与报头分离? 如何将有效载荷交付? 第一个问题由于在报头里面有16位UDP长度(表示的是有效载荷+报头长度),而报头长度8字节是固定的,所以分离时我们只需要用整个报文的大小减去固定的8字节报头数据即

    2024年02月08日
    浏览(66)
  • 计算机网络(2) --- 网络套接字UDP

    计算机网络(1) --- 网络介绍_哈里沃克的博客-CSDN博客 https://blog.csdn.net/m0_63488627/article/details/131967378?spm=1001.2014.3001.5501 目录 1.端口号 2.TCP与UDP协议 1.TCP协议介绍 1.TCP协议 2.UDP协议 3.理解 2.网络字节序 发送逻辑 3.socket 1.介绍 2.sockaddr结构 4.UDP协议编程 1.接口介绍 1.创建套接字

    2024年02月14日
    浏览(49)
  • 计算机网络-传输层(UDP协议报文格式,伪首部,UDP校验过程)

    UDP只在IP数据报服务之上增加了很少功能,即复用分用和差错检测功能。 UDP的主要特点: UDP是无连接的,减少开销和发送数据之前的时延。 UDP使用最大努力交付,即不保证可靠交付。 UDP是面向报文的,适合一次性传输少量数据的网终应用。 应用层给UDP多长的报文,UDP就照样

    2023年04月25日
    浏览(60)
  • [计算机网络] 实验3 UDP协议分析

    实验目的 掌握运输层 UDP 协议内容 理解 UDP 协议的工作原理 了解应用层和运输层协议的关系 实验内容 1.DNS查询UDP数据分析 要求 : 使用 t c p d u m p tcpdump t c p d u m p 抓取 D N S DNS D N S 查询网络通信数据包,利用 w i r e s h a r k wireshark w i r e s h a r k 分析 U D P UDP U D P 数据 例如 : d i

    2023年04月26日
    浏览(48)
  • 计算机网络——18无连接传输UDP

    “尽力而为的”服务,报文段可能 丢失 送到应用进程的报文段乱序 无连接 UDP发送端和接收端之间没有握手 每个UDP报文段都被独立的处理 UDP被用于 流媒体 DNS SNMP 在UDP上实现可靠传输 在应用层增加可靠性 应用特定的差错格式 为什么要有UDP 不建立连接(会增加延时) 简单:

    2024年02月20日
    浏览(43)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包