UDP编程
数据报通信;对于数据报通信的服务器端来说,它不必再在一个端口上侦听,以等待建立连接,而只需生成一个端口描述符,并且把这个端口描述符绑定到本地地址上就可以了。
UDP网络编程具体的操作流程为:
socket()
使用系统调用socket()来获得文件描述符,该调用的声明格式为:
#include <sys/types.h>
#include <sys/socket.h>
int socket<int damain, int type, int protocol);
socket函数说明
bind()
一旦有了一个套接口以后,下一步工作就是把套接口绑定到本地计算机的某一个端口上,但如果只想使用connect()则没有这个必要了。
下面是系统调用bind()的定义:
#include <sys/types.h>
#include <sys/socket.h>
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
bind函数说明
connect()
connect()系统调用由客户端调用,它的用法如下:
#include <sys/types.h>
#include <sys/socket.h>
int connect(int sockfd,struct sockaddr *serv_addr, int addrlen);
connect函数说明
sendto()和recvfrom()
因为数据报套接口是无连接的,它并不连接到远程的主机上,所以在发送数据报之前,必须首先给出目的地址:
这两个函数定义如下:
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
sendto函数说明
recvfrom函数说明
close()和shutdown()
可以使用close()调用关闭连接的套接口文件描述符,它的调用方式为:
close(sockfd);
//这样以后就不能再对此套接口进行任何的读/写操作了。
//使用系统调用shutdown(),可有更多的控制权
int shutdown(int sockfd, int how);
int shutdown(int sockfd, int how)
- 第一个参数是希望切断通信的套接口文件描述符。
- 第二个参数how的值如下
- 0:不允许再接收数据
- 1:不允许再发送数据
- 2:发送和接收数据都不允许
- shutdown()调用成功的返回值为0,如果失败则返回-1
udp服务器端的程序:
/*udpserver.c*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <errno.h>
#define SERVER_PORT 8888//绑定端口
#define MAX_MSG_SIZE 1024//数据最大字节为1024
void udps_respon(int sockfd){
struct sockaddr_in addr;
int addrlen,n;
char msg[MAX_MSG_SIZE];
while(1){
/*等待数据请求*/
n = recvfrom(sockfd,msg,MAX_MSG_SIZE,0,(struct sockaddr*)&addr,&addrlen);
msg[n] = 0;
/*显示服务器已经收到了信息*/
fprintf(stdout, "I have received:%s\n", msg);
fprintf(stdout, "Client Port:%d\n",ntohs(addr.sin_port));
sendto(sockfd,msg,n,0,(struct sockaddr*)&addr,addrlen);
}
}
int main(void){
int sockfd;//定义一个socket描述符
struct sockaddr_in addr;
sockfd = socket(AF_INET,SOCK_DGRAM,0);//给这个描述符赋值
if(sockfd<0){//socket没有收到数据
fprintf(stderr, "Socket Error:%s\n",strerror(errno));
exit(1);
}
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
addr.sin_port = htons(SERVER_PORT);
if(bind(sockfd,(struct sockaddr*)&addr,sizeof(struct sockaddr_in))<0)
{
fprintf(stderr, "Bind Error%s\n",strerror(errno));
exit(1);
}
udps_respon(sockfd);
close(sockfd);
}
udp客户端的程序:
/*客户端程序UDPClient.c,使用方法UDPClient ServerIP ServerPort*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <stdio.h>
#include <unistd.h>
#define MAX_BUF_SIZE 1024
void udpc_requ(int sockfd,const struct sockaddr_in *addr,int len){
char buffer[MAX_BUF_SIZE];
int n;
while(1){
printf("please input message:");
/*从键盘读入,写到服务端*/
scanf("%s",buffer);
//fgets(buffer,MAX_BUF_SIZE,stdin);
printf("input %s,len=%d\n",buffer,strlen(buffer));
//sendto(sockfd,buffer,strlen(buffer),0,addr,len);
sendto(sockfd,buffer,strlen(buffer),0,addr,len);
bzero(buffer,MAX_BUF_SIZE);
/*从网络上读,写到屏幕上*/
n = recvfrom(sockfd,buffer,MAX_BUF_SIZE,0,NULL,NULL);
buffer[n] = 0;
printf("I have received:%s,len=%d\n",buffer,n );
//fputs(buffer,stdout);
}
}
int main(int argc,char **argv){
int sockfd,port;
struct sockaddr_in addr;
if(argc != 3){
fprintf(stderr, "Usage:%sserver_ip server_port\n",argv[0]);
exit(1);
}
if((port = atoi(argv[2]))<0){
fprintf(stderr, "Usage:%sserver_ip server_port\n",argv[0]);
exit(1);
}
sockfd = socket(AF_INET,SOCK_DGRAM,0);
if(sockfd<0){
fprintf(stderr, "Socket Error:%s\n",strerror(errno));
exit(1);
}
/*填充服务端的资料*/
bzero(&addr,sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
if(inet_aton(argv[1],&addr.sin_addr)<0){
fprintf(stderr, "IP error:%s\n", strerror(errno));
exit(1);
}
udpc_requ(sockfd,&addr,sizeof(struct sockaddr_in));
close(sockfd);
}
————————————————————-
后记:
在Linux上运行,我的服务器是CentOS无图形化界面的:
- vim udpserver.c 粘贴保存
- vim udpclient.c 粘贴保存
- gcc -o udpserver udpserver.c 编译命令 :gcc -o 生成文件名 欲编译文件名
- gcc -o udpclient udpclient.c 编译命令 :gcc -o 生成文件名 欲编译文件名
- ./udpserver 运行命令
- ./udpclient 127.0.0.1 8888 运行命令:./运行文件名 服务器地址 服务器端口
- 测试
- Ctrl + “C”关闭程序
测试
在客户端输入:“123456789”
服务器端显示:“123456789”
电脑端打开TCP/UDP测试软件输入:“987654321”
服务器端显示:“987654321”
完美!