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

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

#include

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

#include

#include

#include

#include

#include

#inlcude

#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

{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

#include

#include

#include

#include

#include

#incldue

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

}

好文阅读

评论可见,请评论后查看内容,谢谢!!!评论后请刷新页面。