赞
踩
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();
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结构体长度值。
#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; }
#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; }
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。