zoukankan      html  css  js  c++  java
  • 使用 acl 编写 UDP 网络程序(UDP 重传及可靠性机制)

          在当今网络世界,虽然大部分网络应用都是基于 TCP 的,但有时 UDP 的网络通信也有用武之处。acl 的网络库中不仅提供了基于 TCP 的网络套接字流,同时也提供了 UDP 的网络库(目前 acl 库的网络部分仅提供了基本的 UDP 功能,如果想实现 UDP 重传及可靠性机制,大家可以参考 udt --https://sourceforge.net/projects/udt/ 库)。

          使用 acl 网络库无论编写客户端还是服务器程序,都需要首先调用 acl_vstream_bind 接口绑定本机地址,该函数的定义如下:

    /**
     * 针对 UDP 通信,该函数用来绑定本地 UDP 地址,如果绑定成功,则创建
     * ACL_VSTREAM 对象, 用户可以象调用 ACL_VSTREAM 对象的读写接口
     * @param addr {const char*} 本地 UDP 地址,格式:ip:port
     * @param rw_timeout {int} 读写超时时间(秒)
     * @return {ACL_VSTREAM*} 返回 NULL 表示绑定失败
     */
    ACL_API ACL_VSTREAM *acl_vstream_bind(const char *addr, int rw_timeout);

           然后就可以调用 acl_vstream_read/acl_vstream_write 两个函数以 UDP 方式进行网络数据的读写了,因为 UDP 传输是不保证顺序及可靠性的,所以 acl 网络库中的其它读写函数就不被用在 UDP 读写操作中。

          下面一个简单的 UDP 服务端程序:

    static void udp_server(void)
    {
    	const char *addr = "127.0.0.1:1088";
    	char  buf[4096];
    	int   ret;
    	ACL_VSTREAM *stream = acl_vstream_bind(addr, 0);  /* 绑定 UDP 套接口 */
    
    	if (stream == NULL) {
    		printf("acl_vstream_bind %s error %s
    ", addr, acl_last_serror());
    		return;
    	}
    
    	printf("bind udp addr %s ok
    ", addr);
    
    	while (1) {
    		/* 等待客户端数据 */
    		ret = acl_vstream_read(stream, buf, sizeof(buf) - 1);
    		if (ret == ACL_VSTREAM_EOF) {
    			printf("acl_vstream_read error %s
    ", acl_last_serror());
    			break;
    		}
    
    		/* 输出服务器绑定地址及远程客户端地址 */
    		printf("local addr: %s, peer addr: %s, total: %d
    ",
    			ACL_VSTREAM_LOCAL(stream), ACL_VSTREAM_PEER(stream), i);
    
    		/* 回写数据至客户端 */
    		ret = acl_vstream_write(stream, buf, ret);
    		if (ret == ACL_VSTREAM_EOF) {
    			printf("acl_vtream_writen error %s
    ", acl_last_serror());
    			break;
    		}
    	}
    
    	/* 关闭 UDP 套接字 */
    	acl_vstream_close(stream);
    }

          使用 acl 编写的 UDP 客户端示例如下:

    static void udp_client(void)
    {
    	const char *local_addr = "127.0.0.1:1089";  /* 本客户端绑定的地址 */
    	const char *peer_addr = "127.0.0.1:1088";  /* 服务端绑定的地址 */
    	int   i, ret, dlen;
    	char  buf[1024], data[1024];
    	ACL_VSTREAM *stream = acl_vstream_bind(local_addr, 2);  /* 绑定 UDP 套接口 */
    
    	if (stream == NULL) {
    		printf("acl_vstream_bind %s error %s
    ",
    			local_addr, acl_last_serror());
    		return;
    	}
    	memset(data, 'X', sizeof(data);
    	dlen = sizeof(data);
    	
    	for (i = 0; i < 100; i++) {
    		/* 每次写时需要设定服务端地址 */
    		acl_vstream_set_peer(stream, peer_addr);
    
    		/* 向服务端写入数据包 */
    		ret = acl_vstream_write(stream, data, dlen);
    		if (ret == ACL_VSTREAM_EOF) {
    			printf("acl_vtream_writen error %s
    ",
    				acl_last_serror());
    			break;
    		}
    
    		/* 从服务端读取数据 */
    		ret = acl_vstream_read(stream, buf, sizeof(buf));
    		if (ret == ACL_VSTREAM_EOF) {
    			printf("acl_vstream_read error %s
    ",
    				acl_last_serror());
    			break;
    		}
    	}
    
    	/* 关闭客户端 UDP 套接字 */
    	acl_vstream_close(stream);
    }

           由以上两个例子可以看出,使用 acl 网络库编写 UDP 程序也是非常简单的,但有几点需要注意:

          1、虽然 acl 网络库中的 UDP 功能也借用 ACL_VSTREAM 结构定义及 acl_vstream_xxx 等接口定义,但 UDP 传输依然是数据包式(即非流式),所以 acl 网络库中的有关 TCP 的使用方法在 UDP 中并不适合(如:acl_vstream_readn, acl_vstream_gets);

          2、UDP 传输不保证顺序性及可靠性,所以 acl 网络库在绑定 UDP 端口时允许用户指定读超时时间;

          3、使用 acl 网络库编写 UDP 客户端时,在每次向服务端写数据时,最好每次都先通过 acl_vstream_set_peer 设定服务端绑定地址。

          参考:

          acl 项目下载地址:https://sourceforge.net/projects/acl/

          svn:svn://svn.code.sf.net/p/acl/code/trunk acl-code

          github:https://github.com/zhengshuxin/acl

          udp 服务端示例:aclsamplesudp_server

          udp 客户端示例:aclsamplesudp_client

    https://my.oschina.net/u/568966/blog/309529

  • 相关阅读:
    【第36题】2019年OCP认证12C题库062考试最新考试原题
    004 基本命令 touch cp mv 命令
    003 基本指令 mkdir rm -rf(暴力删除)
    002 文件目录类的指令 cd ls
    001 指定运行级别
    005 抽象工厂模式
    006 使用类加载器加载资源文件
    004 方法反射
    003 属性反射
    003 工厂方法模式
  • 原文地址:https://www.cnblogs.com/findumars/p/5559264.html
Copyright © 2011-2022 走看看