欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

Linux下UDP回声服务器的实现

程序员文章站 2022-03-15 22:23:42
...

首先我们需要了解一下UDP和TCP的区别

TCP面向连接数据的传输方式有三个特点:

A、传输的过程数据不会丢失

B、按顺序传输

C、传输的过程中不存在数据边界

TCP协议是面向连接的套接字:可靠的、按序传递的、基于字节的面向连接的数据传输方式的套接字。

UDP数据的传输方式有四个特点:

A、强调快速传输而非传输顺序

B、传输的数据可能丢失也可能损毁

C、传输的过程中不存在数据边界

D、限制每次传输的数据大小

UDP协议是面向消息的套接字:不可靠的、不按序传递的、以数据的高速传输位目的的套接字。

UDP回声服务器服务端的代码实现:

#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
//相对于TCP来说 UDP的服务器实现缺少了确认步骤
void handle_error(const char* msg)
{
	fputs(msg, stderr);
	fputc('\n', stderr);
	exit(1);
}
int UDP_sever(int argc,char* argv[])
{
    int  ser_sock = -1;
    char message[512] = "";
    struct sockaddr_in servaddr,clientaddr;
    if(argc!=2)
    {
       	printf("usage:% <port>\n", argv[0]);
		handle_error("argement is error!:\n");
	}
	//创建UDP套接字
	//PF_INET IPv4 地址族
	//SOCK_DGRAM   UDP
	ser_sock = socket(PF_INET,SOCK_DGRAM,0);
	if (ser_sock==-1)
	{
		handle_error("create socket failed:");
	}

	//配置端口、地址族及IP地址
	memset(&servaddr, 0, sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons((short)atoi(argv[1]));
	
	//分配套接字地址
	if (bind(ser_sock,(struct 	sockaddr*)&servaddr,sizeof(servaddr)))
	{
		handle_error("bind failed:");
	}

	for(int i = 0;i<10;i++)
	{
		//接收数据
		ssize_t len=recvfrom(ser_sock, message, sizeof(message), 0, (struct sockaddr*)&clientaddr, &clientlen);
		//写入数据
		sendto(ser_sock, message, len, 0, (struct sockaddr*)&clientaddr, clientlen);
	}
	close(ser_sock);
	return 0;
}

UDP回声服务器客户端的代码实现:

int UDP_client(int argc, char* argv[])
{
	//变量声明
	int client_sock;
	struct sockaddr_in serv_addr;
	socklen_t serv_len = sizeof(serv_addr);
	char message[512] = "";
	
	if (argc!=3)
	{
		printf("usage:%s ip port\n", argv[0]);
		handle_error("argement error!");
	}
	//创建套接字
	client_sock = socket(PF_INET, SOCK_DGRAM, 0);
	if (client_sock==-1)
	{
		handle_error("socket create failed!");
	}
	
	//配置端口、地址族及IP地址
	memset(&serv_addr, 0, sizeof(serv_addr));
	serv_addr.sin_family = AF_INET;
	serv_addr.sin_addr.s_addr = inet_addr(argv[1]);
	serv_addr.sin_port = htons((short)atoi(argv[2]));

	while (1)
	{
		printf("input message(q to Quit):");
		//输入数据
		scanf("%s", message);
		//设置退出机制
		if ((strcmp(message,"q")==0)|| (strcmp(message, "Q") == 0))
		{
			break;
		}
		//往服务端写入数据
		ssize_t len=sendto(client_sock, message, strlen(message), 0, (struct sockaddr*)&serv_addr, serv_len);
		//清零存储容器 防止发生数据接收错误
		memset(message, 0, len);
		//接收服务端返回的数据
		recvfrom(client_sock, message, sizeof(message), 0, (struct sockaddr*)&serv_addr, &serv_len);
		//打印接收到的数据
		printf("recv:%s\n", message);

	}
	//关闭套接字
	close(client_sock);
	return 0;
}

UDP与TCP相对而言缺少了 listen与accept的过程,简易来讲就是缺少了 TCP的三次握手和四次挥手的确认过程,所以UDP协议是不可靠的。
UDP是无连接协议,传输速度快,用于传输视频或者直播等数据时,UDP比TCP更具有优势。