您的位置:首页 > 理论基础 > 计算机网络

Linux--网络编程(二)UDP编程

2017-03-19 17:10 309 查看

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
= 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
= 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”



完美!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: