UDP服務器

freeline-x 2022-01-08 03:31:33 阅读数:334

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));

在這裏插入圖片描述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);

參數說明:
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);

參數值說明:
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;
}

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;
}
版权声明:本文为[freeline-x]所创,转载请带上原文链接,感谢。 https://gsmany.com/2022/01/202201080331325185.html