博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Linux网络编程[UDP客户端服务器的编程模型]
阅读量:3747 次
发布时间:2019-05-22

本文共 5439 字,大约阅读时间需要 18 分钟。

Linux网络编程[UDP客户端服务器的编程模型]

  1. 编程模型概述
  2. 相关函数
  3. 实例demo

编程模型概述

从一个图示开始:

这里写图片描述
从上述图示中我们都可以看到,UDP的传输相对来说比TCP传输的时候要简单很多,因为其不需要建立稳定连接,只是相互端口之间的发送,对于一些传输效率需求比较高的应用场景来说,是比较适合的,但是其在稳定性,可靠性上就有一定差异了

相关函数

发送数据:

#include
ssize_t send(int sockfd,const void* buf,size_t nbytes,int flag);(调用connect过后可以直接调用send方法)返回:成功返回发送字节数,出错返回-1ssize_t sendto(int sockfd,const void * buf,size_t nbytes,int flag,const struct sockaddr * destaddr,socklen_t destlen);返回:成功返回发送字节数,出错返回-1ssize_t sendmsg(int sockfd,const struct msghdr *msg,int flag);返回:成功返回发送字节数,出错返回-1struct msghdr{ void *msg_name; /**/ socklen_t msg_namelen;/**/ struct iovec * msg_iov;/**/ int msgiovlen; /**/ void *msg_control;/**/ socklen_t msg_controllen;/**/ int msg_flag;/**/}

接收数据

#include
ssize_t recv(int sockfd,void *buf,size_t nbytes,int flag); ssize_t recvfrom(int sockfd,void * restrict buf,size_t len,int flag,struct sockaddr* restrict addr,socklen_t *restrict addrlen); 一般flag为0; ssize_t recvmsg(int sockfd,struct msghdr *msg,int flag); 返回:返回消息的字节数,无消息返回0,出错返回-1

不多说上代码

/* * =========================================================================== * *       Filename:  udp_server.c *    Description: *    基于udp协议的一个server端的程序(udp协议没有差错校验)面向无连接的不可靠的协议  *        Version:  1.0 *        Created:  2017年05月13日 09时27分26秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
int sockfd;void sig_handler(int signo){ if(signo == SIGINT){ perror("sig interrupt and pid cancel"); exit(1); close(sockfd); }}void out_client_info(struct sockaddr_in *clientaddr){ char ip[16]; int port; memset(ip,0,sizeof(ip)); inet_ntop(AF_INET,&clientaddr->sin_addr.s_addr,ip,sizeof(ip)); port = ntohs(clientaddr->sin_port); printf("client:%s(%d)\n",ip,port);}void do_service(){ struct sockaddr_in clientaddr; socklen_t len = sizeof(clientaddr); char buff[1024]; memset(&clientaddr,0,len); ssize_t size = recvfrom(sockfd,buff,sizeof(buff),0,(struct sockaddr *)&clientaddr,&len); if(size < 0 ){ printf("recv error"); }else{ out_client_info(&clientaddr); printf("client send info:%s\n",buff); time_t t = time(0); char *ptr = ctime(&t); ssize_t time_size = strlen(ptr) * sizeof(char); if(sendto(sockfd,ptr,time_size,0,(struct sockaddr*)&clientaddr,len) < 0){ perror("send to error"); } }}int main(int argc,char *argv[]){ //确定绑定的端口,从命令行传入参数,第二个参数是绑定端口的参数 if(argc < 2){ printf("usage :%s port\n",argv[0]); exit(EXIT_FAILURE); } if(signal(SIGINT,sig_handler) == SIG_ERR){ perror("signal sigint error"); exit(EXIT_FAILURE); } /* * *创建socket * * */ sockfd = socket(AF_INET,SOCK_DGRAM,0); if(sockfd < 0 ){ perror("socket create error"); exit(EXIT_FAILURE); } int res; int opt = 1; /* * *设置端口停止后,后续端口能够立马再次使用 * */ if((res = setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))) <0){ perror("setsockopt error"); exit(1); } /* * *调用bind函数对socket和地址进行绑定 sockaddr--->socket通用地址 sockaddr_in--->socket专用地址 * */ struct sockaddr_in addr_in; memset(&addr_in,0,sizeof(addr_in)); addr_in.sin_family = AF_INET; //IPV4 addr_in.sin_port = htons(atoi(argv[1])); //端口必须要是网络字节序 addr_in.sin_addr.s_addr = INADDR_ANY; //获得主机上面所有ip地址的请求 if(bind(sockfd,(struct sockaddr *)&addr_in,sizeof(addr_in)) < 0){ //对端口进行绑定 perror("bind error"); exit(EXIT_FAILURE); } /* * * * */ while(1){ do_service(); } return 0;}
/* * =========================================================================== * *       Filename:  udp_client.c *    Description:  基于udp协议的一个client端 *        Version:  1.0 *        Created:  2017年05月13日 10时09分41秒 *       Revision:  none *       Compiler:  gcc *         Author:   (),  *        Company:   * * =========================================================================== */#include
#include
#include
#include
#include
#include
#include
int client_sockfd;int main(int argc,char * argv[]){ if(argc < 3){ printf("usage :%s ip port\n",argv[0]); exit(EXIT_FAILURE); } client_sockfd = socket(AF_INET,SOCK_DGRAM,0); if(client_sockfd < 0 ){ perror("create client socket error"); exit(EXIT_FAILURE); } /** *一般在客户端是不需要去进行绑定操作的,调用recv和sendto进行双向通信 */ struct sockaddr_in serveraddr; memset(&serveraddr,0,sizeof(serveraddr)); serveraddr.sin_family = AF_INET; //IPV4 serveraddr.sin_port = htons(atoi(argv[2]));//端口 inet_pton(AF_INET,argv[1],&serveraddr.sin_addr.s_addr); //ip /* * *注意:如果在udp中调用connect的话,不会进行握手动作,只是在内核中去记住了地址信息,这个时候可以直接使用send去发送信息,而不需要再去进行调用sendto函数 调用connect的好处就是客户端接收到的数据报文仅仅是服务器发过来的,如果不去调用的话,则很有可能是其他服务器发过来的 * * */ int connect_result; connect_result = connect(client_sockfd,(struct sockaddr*)&serveraddr,sizeof(serveraddr)); if(connect < 0){ perror("connect error"); exit(EXIT_FAILURE); } char buff[1024] = "helloworld"; ssize_t client_size_t; client_size_t = sendto(client_sockfd,buff,sizeof(buff),0,(struct sockaddr*)&serveraddr,sizeof(serveraddr)); if(client_size_t < 0){ perror("sendto error"); exit(1); } else { memset(buff,0,sizeof(buff)); size_t size; size = recv(client_sockfd,buff,sizeof(buff),0); if(size <0){ perror("recv error"); exit(EXIT_FAILURE); }else{ printf("%s",buff); } } close(client_sockfd); return 0;}

代码都是经过调试的,udp_server端负责去接收client发过来的报文信息.

由于最近个人事情比较多,所有很长一段时间都没有去更新了.

你可能感兴趣的文章
基本类型包装类
查看>>
System类常用方法
查看>>
Runtime类、Math类和Random类的常用方法
查看>>
数据处理类常用方法
查看>>
Collections和Character类 常用静态方法
查看>>
HTML之Javascript——BOM浏览器对象模型
查看>>
JAVA基础中的基础
查看>>
JDBC基础操作
查看>>
连接池
查看>>
Servlet的使用——重定向和转发
查看>>
JSP技术的使用——好像过时了唉。。。。。
查看>>
MVC模式概述
查看>>
Web之过滤器Filter
查看>>
JSON和AJAX
查看>>
web之监听器listener
查看>>
类加载器
查看>>
数据库设计
查看>>
Java虚拟机的内存分配和运行机制(粗谈)
查看>>
web开发之BaseServlet的使用
查看>>
初识Maven
查看>>