当前位置:   article > 正文

UDP服务器

udp服务器

UDP传输不可靠,传输数据的正确率、传输顺序和流量都得不到控制和保证。所以,通常情况下,使用UDP协议进行数据传输,为保证数据的正确性,我们需要在应用层添加辅助校验协议来弥补UDP的不足

与TCP类似,UDP也有可能出现缓冲区被填满后,再接收数据时丢包的现象。由于它没有TCP滑动窗口的机制,通常采用如下方法解决:
1)服务器应用层设计流量控制,控制发送数据速度
2)借助setsockopt函数改变接收缓冲区大小。比如:

#include <sys/socket.h>
int setsockopt(int sockfd,int level,int optname,const void*optval,socklen_t optlen);
int n = 220x1024;
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&n,sizeof(n));
  • 1
  • 2
  • 3
  • 4

在这里插入图片描述UDP通信的过程:
服务端:
1)使用函数socket,生成套接字描述符
2)设置struct sockaddr_in结构设置服务器地址和监听端口
3)使用bind()函数绑定监听端口,将套接字文件描述符和地址类型变量 sockaddr_in进行绑定
4)接收客户端的数据,使用recvfrom()函数接收客户端的网络数据;
5)向客户端发送数据,使用sendto()函数向服务器主机发送数据;
6)关闭套接字,使用close()函数释放资源
客户端:
1)使用socket,生成套接字文件描述符
2)通过struct sockaddr_in结构设置服务器地址和监听端口
3)向服务器发送数据,sendto();
4)接收服务器的数据,recvfrom();
5)关闭套接字,clsoe();

1、API

int sendto(int s,const void *buf,int len,unsigned int flags,const struct sockaddr *to,int tolen);
  • 1

参数说明:
s:socket描述符
buf:UDP数据报缓存区(包含待发送数据)
len:UDP数据的长度
flags:调用方式标志位(一般设置为0)
to:指向接收数据的主机地址信息的结构体(sockaddr_in需类型转换)
tolen:to所指向结构体的长度
返回值说明:
成功则返回实际传送出去的字符数,失败返回-1,错误原因会存于errno中。

int recvfrom(int s,void*buf,int len,unsigned int flags,struct sockaddr*from,int *fromlen);
  • 1

参数值说明:
s:socket描述符
buf:UDP数据缓存区(包含所接收的数据)
len:缓冲区长度
flags:调用操作方式(一般设置为0)
from:指向发送数据的客户端地址信息的结构体(sockaddr_in需要类型转换)
fromlen:指针,指向from结构体长度值。

2、server端

#include <string.h>
#include <netinet/in.h>
#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <arpa/inet.h>
#inlcude <ctype.h>

#define MAXLINE 80
#deifine SERV_PORT 5000

int main(void)
{
	struct sockaddr_in servaddr,cliaddr;
	socklen_t cliaddr_len;
	int sockfd;
	char buf[MAXLINE];
	char str[INET_ADDRSTRLEN];
	int i,n;

	sockfd = socket(AF_INET,SOCK_DGRAM,0);
	
	bzero(&servaddr,sizeof(servaddr));
	servaddr.sin_family = AF-INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(SERV_PORT);

	bind(sockfd,(struct sockadr *)&servadr,sizeof(servaddr));
	printf("Accepting connections ...\n");
	while(1){
		cliaddr_len = sizeof(cliaddr);
		n = recvfrom(sockfd,buf,MAXLINE,0,(struct sockaddr *)&cliaddr,&cliaddr_len);
		if(n == 1)
		{perror("recvfrom error");}
		printf("received from %s at PORT %d\n",
			inet_ntop(AF_INET,&cliaddr.sin_addr,str,sizeof(str)),
			ntohs(cliaddr.sin_port));
		for(i = 0; i<n;i++)
		{buf[i] = toupper(buf[i]);}
		n = sendto(sockfd,buf,n,0,(struct sockaddr *)&cliaddr,sizeof(cliaddr));
		if(n == -1)
		{perror("sendto error");}
	}
close(sockfd);
return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46

3、 client端

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <strings.h>
#incldue <ctype.h>

#define MAXLINE 80
#define SERV_PORT 5000

int mian (int argc,char *argv[])
{
	struct sockaddr_in servaddr;
	int sockfd,n;
	char buf[MAXLINE];
	
	sockfd = socket(AF_INET,SOCK_DGRAM,0);
	
	bzero(&servaddr,sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	inet_pton(AF_INET,"127.0.0.1",&servaddr.sin_addr);
	servaddr.sin_port = htons(SERV_PORT);
	
	while(fgets(buf,MAXLINE,stdin)!=NULL){
		n = sendto(sockfd,buf,strlen(buf),0,(struct sockaddr*)&servaddr,sizeof(servaddr));
		if(n == -1)
		{perror("sendto error");}
		n = recvfrom(sockfd,buf,MAXLINE,0,NULL,0);
		if(n == -1)
		{perror("recvfrom error");}
		write(STDOUT_FILENO,buf,n);
	}
	close(sockfd);
	return 0;
}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
本文内容由网友自发贡献,转载请注明出处:【wpsshop博客】
推荐阅读
相关标签
  

闽ICP备14008679号