网络编程二(UDP)

本文探讨了UDP在网络编程中的应用,包括C/S-UDP模型、UDP广播和组播。针对UDP可能出现的丢包问题,提出了服务器应用层的流量控制和设置缓冲区大小的解决方案。还介绍了如何赋予socket广播权限以及实现广播和组播的示例代码。
摘要由CSDN通过智能技术生成

网络编程二(UDP)

在这里插入图片描述UDP可能出现缓冲区被填满,再次接收数据会出现丢包的情况.UDP没有滑动窗口机制,所以靠以下方法解决:
1>在服务器应用层设计流量控制,控制发送数据的速度;
2>使用setsockopt()函数修改缓冲区大小.

#include<sys/socket.h>
//原型:int setsockopt(int sockfd,int level,int optname,const void *optval,socklen_t optlen);
int n 220*1024
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&n,sizeof(n));

1UDP实现应用场景

  • 控制函数
/***********************socket函数********************************
	*函数1:socket()  
	*头文件:#include <sys/types.h>  #include <sys/socket.h>
	*格式:int socket(int domain, int type, int protocol);
	*参数:int domain:AF_UNIX(本地套接字);AF_INET(ipv4);AF_INET6(ipv6)
	*参数:int type(传输协议重点两个值):SOCK_STREAM(最常用)(基于字节流TCP-可靠);SOCK_DGRAM(无连接,固定长度,基于UDP协议-不可靠)
	*参数:int protocol:一般传0;指定默认协议(及第二个参数的默认协议,TCP\UDP)
	*作用:创建套接字
	*返回值: 成功-fd(文件描述符);失败--1;
	********************************************************
	*函数2:bind() 
	*头文件:#include <sys/types.h>  #include <sys/socket.h>
	*格式:  int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
	*参数:int sockfd:socket()函数返回的文件描述符;
	*参数:const struct sockaddr *addr:创建socket数据结构,指定IP地址和端口号(注意)
	struct sockaddr_in {
						   sa_family_t    sin_family;  //address family: AF_INET 
						   in_port_t      sin_port;    //port in network byte order 
						   struct in_addr sin_addr;   //internet address 
                      };
           /* Internet address. 
     struct in_addr  {
               			 uint32_t       s_addr;     //address in network byte order 
                     };
	eg:struct sockaddr_in addr;
		addr.sin_family=AF_INET\AF_INET6;
		addr.sin_port=htons()/ntops()		//   注意端口号需要调用函数转化字节序
		addr.sin_addr.s_addr=htons()/ntops() /inet_ntop()/inet_pton() //注意IP也需要调用函数转化字节序
	*参数:socklen_t addrlen:传入sizeof(addr)
	*作用:将socket()函数返回的fd与addr(IP和端口号)绑定在一起,进而使用fd监听IP和端口号;
	*返回值: 成功-0;失败--1;
	********************************************************
	*函数3:
	*头文件: #include <sys/types.h> #include <sys/socket.h>
	*格式:  ussize_t recvfrom(int sockfd, void *buf, size_t len, int flags,struct sockaddr *src_addr, socklen_t *addrlen);
	*参数:int sockfd:socket文件描述符
	*参数:void *buf:接收数据的buffer
	*参数:size_t len:buffer大小
	*参数:int flags:标志位,0-相当于read()函数
	*参数:struct sockaddr *src_addr:传出参数,存储client信息的,sendto()函数需要使用
	*参数:socklen_t *addrlen:传入传出参数,client_addr_len
	*作用:从socket接收数据
	*返回值:These  calls  return  the  number  of bytes received, or -1 if an error occurred.  In the event of an error,  errno  is  set  to  indicate  the error.
	********************************************************
	*函数4: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);
	*参数:int sockfd:socket文件描述符
	*参数:void *buf:发送数据的buffer
	*参数:size_t len:buffer大小
	*参数:int flags:标志位,0-相当于read()函数
	*参数: const struct sockaddr *dest_addr:传入参数,传入client信息的(才知道信息发给谁-所以不能传空)
	*参数:socklen_t addrlen:第三个参数结构体的大小
	*作用:向socket发送数据
	*返回值: On success, these calls return the number of bytes sent.  On error, -1 is returned, and errno is set appropriately.
	********************************************************
	*函数5:htonl()\htons()\ntohl()\ntohs
	*头文件:#include <arpa/inet.h>
	*格式:  uint32_t htonl(uint32_t hostlong);\\htonl:h-host(主机);to;n-network(网络);l-long(4字节,对应的IP为4字节);s-short int (2字节,对应端口号为2字节)

      		 uint16_t htons(uint16_t hostshort);

      		 uint32_t ntohl(uint32_t netlong);

       		 uint16_t ntohs(uint16_t netshort);
	*作用:主机字节序\网络字节序转换
	********************************************************
	*函数6:inet_pton() \inet_ntop()(更方便)
	*头文件:#include <arpa/inet.h>
	*格式:  int inet_pton(int af, const char *src, void *dst);//int af(指定ipv4还是ipv6):AF_INET或则AF_INET6; const char *src(传入参数,ip地址字符串的首地址);void *dst:传出参数,转换为网络字节序
		const char *inet_ntop(int af, const void *src,char *dst, socklen_t size);int af(指定ipv4还是ipv6):AF_INET或则AF_INET6;const char *src(传入参数,传入ip网络字节序);char *dst:(传出参数,传出主机字节序的ip字符串);socklen_t size:(第三个参数的长度)
	*作用:inet_pton()-主机字节序(点分十进制)to网络字节序;inet_ntop:相反
	*返回值:On success, inet_ntop() returns a non-null pointer  to  dst.   NULL  is returned if there was an error, with errno set to indicate the error.
	*****************************socket函数**************************/
/*注意:1.定义的时候要定义为sockaddr_in,在做形参的时候要转化为(struct sockaddr *)类型,涉及的函数有bind()\accept()\connect();因为sockaddr_in是后来改的名字;函数不认
	2.ipv6的数据结构又不一样
	3.eg:
		struct sockaddr_in addr;
		addr.sin_family=AF_INET\AF_INET6;
		addr.sin_port=htons()/ntops()		//   注意端口号需要调用函数转化字节序
		addr.sin_addr.s_addr=htons()/ntops() /inet_ntop()/inet_pton() //注意IP也需要调用函数转化字节序*/

1>C/S-UDP模型

在这里插入图片描述

  • server.c
#include<stdio.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <ctype.h>
#include<unistd.h>
#include<stdlib.h>
#include <errno.h>
#include<string.h>
#include <sys/types.h>

#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 8080

int main(int argc, char *argv[])
{
   
	int n; //recvfrom()函数返回值
	int i;
	char buffer[1024];   //存储传输数据
	char buf[1024];//存放ip的,协议用的32位存放(数值型 unsigned int),而主机是存放的字符串类型,所以可以尽量开大一点.
	//1.创建socket-ipv4,默认报式协议UDP
	int fd=socket(AF_INET, SOCK_DGRAM, 0);
	if(fd==-1)
	{
   
		perror("socke error");
		exit(1);
	}
	//2.绑定端口
	struct sockaddr_in server_addr,client_addr;
	socklen_t client_addr_len=sizeof(client_addr);

	memset(&server_addr, 0, sizeof(server_addr));
	server_addr.sin_family=AF_INET;
	server_addr.sin_port=htons(SERVER_PORT);
	inet_pton(AF_INET,SERVER_IP,&server_addr.sin_addr.s_addr);
	int ret1=bind(fd,(struct sockaddr *)&server_addr,sizeof(server_addr));
	if(ret1==-1)
	{
   
		perror("bind error");
		exit(1);
	}
	printf("Waiting connect....\n");
	while(1)
	{
   
		//3.接收数据
		n=recvfrom(fd,buffer,sizeof(buffer),0,(struct sockaddr *)&client_addr,&client_addr_len);  //会阻塞读
		if(n==-1)
		{
   
			perror(
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值