udp之服务器和客户端

UDP全称:User Datagram Protocol,通过IP协议提供无连接、不稳定的通信服务。
下面的可以先跳过,先测试客户端和服务端的代码,有个基本的认识再看下面的东西。
UDP有如下特点

  • UDP是无连接的,在发送数据之前不与对方建立连接
  • UDP不对数据进行排序,UDP报文头部没有数据顺序信息,可能后发送的先到
  • 对数据不发送确认,发送端不知道数据是否被正确接受,也不会重发数据
  • 传送数据比TCP快,系统开销也小
  • 缺乏拥塞控制机制,不能够检测到网络拥塞

UDP数据帧

|-------------------UDP头部(8字节)------------------------------------|---UDP数据----|
|-源端口号(2字节)-|-目的端口号(2字节)-|-长度(2字节)-|-校验和(2字节)-|-数据(N个字节)-|

这里源端口号可为0,目的端口号一定要有,长度是数据的长度,检验和用于校验数据在传输过程中是否出错,出错数据就会被丢弃

在计算校验和的时候,会在UDP前面加上伪首部,伪首部不会向下传送也不向上递交,仅用于计算检验和,模仿的是IP首部

客户端代码

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

static int udp_socket=-1;
struct sockaddr_in serveraddr;

void udp_init()
{
	printf("udp init\n");
}


void udp_write()
{
	 //第三步:发送数据
    char buf[12] = "789";	
	socklen_t addrlen = sizeof(serveraddr);
	if(sendto(udp_socket,buf,3,0,(struct sockaddr *)&serveraddr,addrlen) == -1)
    {
        perror("fail to sendto");
        return;
    }

}

int udp_test()
{
	//第一步,创建一个用于UDP通信的套接字
	udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
	if(udp_socket<0)
	{		
		perror("open error ");
		return -1;
	}
	printf("udp_socket=%d\n",udp_socket);
	
	//第二步,绑定服务器的IP和端口	
	/*
	struct in_addr
	{
		in_addr_t s_addr;//IP 地址4字节
	};
	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 sockaddr
	{
		sa_family_t sa_family; //2字节
		char sa_data[14] //14字节
	}
	*/
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr("192.168.2.171");
	serveraddr.sin_port = htons(atoi("7788"));
	
	return 0;
}

服务器端代码

#include"udp.h"
#include<stdio.h>
#include<stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/udp.h>
#include <errno.h>
#include <arpa/inet.h>

static int udp_socket=-1;

void udp_init()
{
	printf("udp init\n");
}

void udp_read()
{
	 //第三步:接收数据
    char buf[128] = "";
    struct sockaddr_in clientaddr;
    socklen_t addrlen = sizeof(struct sockaddr_in);
	
	if(recvfrom(udp_socket,buf,28,0,(struct sockaddr *)&clientaddr,&addrlen) == -1)
	{
	   perror("fail to recvfrom");
	   return ;
	}
	   //打印数据
	   //打印客户端的ip地址和端口号
	   printf("ip:%s,port:%d\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
	   //打印接收到的数据
	   printf("from client: %s\n",buf);

}

int udp_test()
{
	//第一步,创建一个用于UDP通信的套接字
	udp_socket = socket(AF_INET, SOCK_DGRAM, 0);
	if(udp_socket<0)
	{		
		perror("open error ");
		return -1;
	}
	printf("udp_socket=%d\n",udp_socket);
	
	//第二步,绑定服务器的IP和端口	
	/*
	struct in_addr
	{
		in_addr_t s_addr;//IP 地址4字节
	};
	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 sockaddr
	{
		sa_family_t sa_family; //2字节
		char sa_data[14] //14字节
	}
	*/
	
	struct sockaddr_in serveraddr;
	serveraddr.sin_family = AF_INET;
	serveraddr.sin_addr.s_addr = inet_addr("192.168.2.70");
	serveraddr.sin_port = htons(atoi("7788"));
	if(bind(udp_socket,(struct sockaddr*)&serveraddr,sizeof(serveraddr)) == -1)
	{
	   perror("fail to bind");
	   return -1;
	}
	return 0;
}
posted @ 2023-09-25 16:13  njit-sam  阅读(298)  评论(0编辑  收藏  举报