服务器端代码的基本结构都差不多。
首先是创建一个socket address对象,类型是apr_sockaddr_t,可以用它提供的api:
APR_DECLARE(apr_status_t) apr_sockaddr_info_get(apr_sockaddr_t **sa,
const char *hostname,
apr_int32_t family,
apr_port_t port,
apr_int32_t flags,
apr_pool_t *p);

其中第1个参数是要创建的对象;第2个是主机名,也可以写ip地址;第3个APR_INET,代表ipv4。ipv6的话可以用APR_INET6;第4个参数是监听端口;第5个flag写0就行了;第6个也就是最后一个参数就是pool内存池。
一个例子是:   
apr_sockaddr_t *sa;    
rv = apr_sockaddr_info_get(&sa, NULL, APR_INET, DEF_LISTEN_PORT, 0, mp);
第2个参数指定为NULL的意思是(摘自apr-tutorial):
What value is allowed as a local address? One choice is a solid address or hostname. Namely, if you are creating a yahoo server, you can specify "www.yahoo.com" or "66.94.230.38". In general, such values are supplied by configuration files. Second choice is loopback address, i.e. "127.0.0.1" or "localhost". It works and it's valid. However, in such a case, only a client process running on the same host can connect to the server. If your purpose is to allow only local processes to connect to your server, specifying loopback address is a right choice. The other choice is to specify NULL or APR_ANYADDR(="0.0.0.0"). They imply that the server will bind all network interfaces to a socket. Accordingly, in such a case, any client process can connect to the server via a solid address or loopback address. Internally, NULL is better than APR_ANYADDR. As a result, it's usually good to specify NULL as the second argument of apr_sockaddr_info_get(). There is one exception. When the server host is multihome host, i.e. it has multiple solid IP addresses, and you don't want some IP addresses available from remote hosts, you shouldn't specify NULL. You must bind solid IP addresses to the listening socket.

其次是创建一个socket对象,类型是apr_socket_t,可以用它提供的api:
APR_DECLARE(apr_status_t) apr_socket_create(apr_socket_t **new_sock, 
                                            int family, int type,
                                            int protocol,
                                            apr_pool_t *p);
前2个参数就不用说了,第3、4个参数一般有两种组合用法:一种是“SOCK_STREAM as type and APR_PROTO_TCP as protocol”,
另一个种用法是“SOCK_DGRAM as type and APR_PROTO_UDP as protocol”。最后一个参数也不用说了。

然后,有了两个对象后,就可以把socket address对象绑定到socket对象,api是:
apr_socket_bind(apr_socket_t * s, apr_sockaddr_t * sa);

最后,让这个socket对象去监听端口吧:
apr_socket_listen(apr_socket_t * s, SOMAXCONN);

至此,一个最简单的服务器端socket从创建到监听的过程就完成了,总结一下四部曲:
/* default listen port number */
#define DEF_LISTEN_PORT 8081
/* default socket backlog number. SOMAXCONN is a system default value */
#define DEF_SOCKET_BACKLOG SOMAXCONN
apr_sockaddr_t *sa;
apr_socket_t *s;

apr_sockaddr_info_get(&sa, NULL, APR_INET, DEF_LISTEN_PORT, 0, mp);
apr_socket_create(&s, sa->family, SOCK_STREAM, APR_PROTO_TCP,mp);
apr_socket_bind(s, sa);
apr_socket_listen(s, DEF_SOCKET_BACKLOG);

当socket在端口监听时,若有远程连接来访问,则该监听socket要派生出一个小socket去处理,自己则继续监听:
apr_socket_t *ns;/* accepted socket */
apr_socket_accept(&ns, s, mp);
上面那个ns就是派生出的小socket,监听socket 大s则继续监听。

那么这个小s一般都干嘛呢?最简单的动作就是接受和发送消息,有两个api可以做到这两点:

/* excerpted from apr_network_io.h */

APR_DECLARE(apr_status_t) apr_socket_send(apr_socket_t *sock, const char *buf, 
apr_size_t *len);
APR_DECLARE(apr_status_t) apr_socket_recv(apr_socket_t *sock, 
char *buf, apr_size_t *len);

前两个参数就不用说了,第3个参数指具体的消息长度,比如在send中表示具体发送的长度,在recv中表示具体接受到的长度。

server端:

#include <iostream>
#include "apr_network_io.h"
using namespace std;#pragma comment(lib,"libapr-132d.lib")int main()
{apr_initialize();apr_status_t ret = APR_SUCCESS;apr_pool_t *local_pool = NULL;apr_sockaddr_t *sa = NULL;apr_socket_t *new_socket = NULL;apr_pool_create(&local_pool,NULL);ret = apr_sockaddr_info_get(&sa, NULL, APR_INET, 6868, 0, local_pool);if (APR_SUCCESS != ret){cout<<"apr_sockaddr_info_get fail!,ret = "<<ret<<endl;goto error;}ret = apr_socket_create(&new_socket, sa->family, SOCK_STREAM, APR_PROTO_TCP, local_pool);if (APR_SUCCESS != ret){cout<<"create socket fail!,ret = "<<ret<<endl;goto error;}ret = apr_socket_bind(new_socket, sa);if (APR_SUCCESS != ret){cout<<"apr_socket_bind fail!,ret = "<<ret<<endl;goto error;}ret = apr_socket_listen(new_socket, SOMAXCONN);if (APR_SUCCESS != ret){cout<<"apr_socket_listen fail!,ret = "<<ret<<endl;goto error;}//当socket在端口监听时,若有远程连接来访问,则该监听socket要派生出一个小socket去处理,自己则继续监听:apr_socket_t *ns = NULL;ret = apr_socket_accept(&ns, new_socket, local_pool);if (APR_SUCCESS != ret){cout<<"apr_socket_accept fail!,ret = "<<ret<<endl;goto error;}char buffer[1024] = {0};apr_size_t len = 1023;ret = apr_socket_recv(ns, buffer, &len);if (APR_SUCCESS != ret){cout<<"apr_socket_recv fail!,ret = "<<ret<<endl;goto error;}cout<<"server recv buffer = "<<buffer<<"recv len = "<<len<<endl;const char *sendBuff = "world!";apr_size_t sendLen = strlen(sendBuff);ret = apr_socket_send(ns, sendBuff, &sendLen);if (APR_SUCCESS != ret){cout<<"send fail!,ret = "<<ret<<endl;goto error;}cout<<"server,send buffer = "<<sendBuff<<",sendlen = "<<sendLen<<endl;if(new_socket){apr_socket_close(new_socket);}if (ns){apr_socket_close(ns);}apr_pool_destroy(local_pool);apr_terminate();return 0;
error:if(new_socket){apr_socket_close(new_socket);}if (ns){apr_socket_close(ns);}apr_pool_destroy(local_pool);apr_terminate();return -1;
}

client端:

#include <iostream>
#include "apr_network_io.h"
using namespace std;#pragma comment(lib,"libapr-132d.lib")int main()
{apr_initialize();apr_status_t ret = APR_SUCCESS;apr_pool_t *local_pool = NULL;apr_sockaddr_t *sa = NULL;apr_socket_t *new_socket = NULL;apr_pool_create(&local_pool,NULL);ret = apr_sockaddr_info_get(&sa, "192.190.10.103", APR_INET, 6868, 0, local_pool);if (APR_SUCCESS != ret){cout<<"apr_sockaddr_info_get fail!,ret = "<<ret<<endl;goto error;}ret = apr_socket_create(&new_socket, sa->family, SOCK_STREAM, APR_PROTO_TCP, local_pool);if (APR_SUCCESS != ret){cout<<"create socket fail!,ret = "<<ret<<endl;goto error;}ret = apr_socket_connect(new_socket, sa);if (APR_SUCCESS != ret){cout<<"apr_socket_connect fail!,ret = "<<ret<<endl;goto error;}const char *buffer = "hello!";apr_size_t len = strlen(buffer);cout<<"client,send buffer = "<<buffer<<endl;ret = apr_socket_send(new_socket, buffer, &len);if (APR_SUCCESS != ret){cout<<"apr_socket_send fail!,ret = "<<ret<<endl;goto error;}cout<<"client,send len = "<<len<<endl;char recvBuf[1024] = {0};apr_size_t recvLen = 1023;ret = apr_socket_recv(new_socket, recvBuf, &recvLen);if (APR_SUCCESS != ret){cout<<"apr_socket_recv fail!,ret = "<<ret<<endl;goto error;}cout<<"client,recv buffer = "<<recvBuf<<",recv len = "<<recvLen<<endl;if(new_socket){apr_socket_close(new_socket);}apr_pool_destroy(local_pool);apr_terminate();return 0;
error:if(new_socket){apr_socket_close(new_socket);}apr_pool_destroy(local_pool);apr_terminate();return -1;
}

apr_socket 编程相关推荐

  1. C++核心编程(一)

    C++ 核心编程 本系类列博客都是根据黑马的C++视频做的笔记. 本阶段主要针对C++面向对象编程技术做详细记录,探讨C++中的核心和精髓. 1.内存分区模型 C++程序在执行时,将内存大方向划分为4 ...

  2. 【Spring】面向切面编程AOP

    AOP基础 什么是AOP [废话解释]在软件业,AOP全称Aspect Oriented Programming 即:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术.AO ...

  3. python编程问题--第二次

    本质上grp 是一个dataframe 后面接一个[] 得到 series 两个[] 得到dataframe Groupby 如果后面放as_index=False 后面就能连续添加了 不加的话  同 ...

  4. OpenCL编程详细解析与实例

    OpenCL编程详细解析与实例 C语言与OpenCL的编程示例比较 参考链接: https://www.zhihu.com/people/wujianming_110117/posts 先以图像旋转的 ...

  5. C语言与OpenCL的编程示例比较

    C语言与OpenCL的编程示例比较 OpenCL支持数据并行,任务并行编程,同时支持两种模式的混合.对于同步 OpenCL支持同一工作组内工作项的同步和命令队列中处于同一个上下文中的 命令的同步. 在 ...

  6. LLVM一些编程语法语义特性

    LLVM一些编程语法语义特性 High Level Structure Module Structure LLVM 程序由Module's组成,每个 's 是输入程序的一个翻译单元.每个模块由函数.全 ...

  7. Structured Streaming编程 Programming Guide

    Structured Streaming编程 Programming Guide • Overview • Quick Example • Programming Model o Basic Conc ...

  8. TensorFlow编程结构

    TensorFlow编程结构 TensorFlow 与其他编程语言非常不同. 首先通过将程序分为两个独立的部分,构建任何拟创建神经网络的蓝图,包括计算图的定义及其执行.起初这对于传统程序员来说看起来很 ...

  9. MindSpore API编程概述

    MindSpore API编程概述 总体架构 MindSpore是一个全场景深度学习框架,旨在实现易开发.高效执行.全场景覆盖三大目标,其中易开发表现为API友好.调试难度低,高效执行包括计算效率.数 ...

最新文章

  1. 华为这台「技术暴力输出机」,亮出「云原生2.0」,研发效率飙升10倍!
  2. fpga经典设计100例_图解运放电路/OP放大电路设计/OP放大器应用技巧100例
  3. CVE-2019-0708(BlueKeep)漏洞分析与复现
  4. JavaScript实现将位转换为浮点数bitsToFloat算法(附完整源码)
  5. python安装redis模块_安装redis及python redis模块
  6. 红象云腾发布新一代PB级高速大数据平台产品
  7. 写一函数,将一个字符串中的元音字母复制到另一个字符串,然后输出
  8. 数据结构基础(15) --基数排序
  9. 使用Android自带DownloadManager下载文件
  10. sqlserver openrowset mysql_sqlserver连接mysql
  11. 【Java程序设计】输入输出
  12. html div重叠上方,html – 将父div上方的子div对齐到右边,不要重叠
  13. 超三十万台设备感染银行木马、远程代码漏洞可攻击云主机|12月7日全球网络安全热点
  14. (22) 基于动态时空图卷积神经网络的交通流预测
  15. jmeter性能测试2-模拟多用户登录
  16. huawei.xmind
  17. java在pdf文件中插入字_怎么在PDF文件中添加文字文本框
  18. css视差滑动(阅读网站案例)
  19. 前端:让我们做一个快乐的切图仔!
  20. 如何使用docker和docker-compose在本地Testnet上开发EOS区块链

热门文章

  1. ipv6学习笔记(手写版)
  2. 日落MFC-工具栏CToolBar自定义图标
  3. 【Excel函数】Office 365 之Excel函数之Left函数
  4. 在美上市公司的员工,拥有一个美股账户的好处
  5. 联想电脑获取官方原厂系统镜像的方法
  6. 基于Python机器学习方法的电影推荐系统
  7. 题1024. 视频拼接
  8. 炫酷感科技感旋转vuejsjs特效
  9. pdf怎么压缩的小一点?pdf压缩大小如何压缩?
  10. 阿里云物联网平台MQTT设备接入