如何做一个国产数据库一
如何做一个国产数据库二
如何做一个国产数据库三
如何做一个国产数据库四
如何做一个国产数据库五

网络实战服务器

我们再四中说过使用tcp进行协议的链接,对我们所定义的协议如果有不清楚的,我们可以再看一下四,示例使用libuv进行服务器编程,uv是一个异步网络库。

除了协议,再次定义一下我们网络的数据结构

//客户端数据结构
typedef struct client_t {//tcp client sessionuv_tcp_t tcp;//解析使用tcp_settings * config = NULL;//写入uv_write_t write_req;//设备iduint32_t   deviceid = 0;//读入的内容tcp_unit   *buffer_data = NULL;//需要写入的内容tcp_unit_w *buffer_data_w = NULL;//最长6字节包头char head[6];//已经接收的头部的长度int recvlen;//用户自定义数据指针 tcpservervoid * data = NULL;//接收状态 接收头部,0 接收数据 1recv_status status = enum_head; //是否在线int is_online = enum_online;uv_timer_t  _timer;uv_thread_t _thread;int thread_run = 0;int time_init() {if (config == NULL)return -1;uv_timer_init(config->uv_loop, &_timer);return 0;}client_t() {}void clean(){free_unit(&buffer_data);}int headlen() {return recvlen;}
}client_t;

工作队列数据结构

typedef struct thread_work {thread_work(client_t* cli, tcp_unit * unit) :request(),client(cli),data(unit),error(false) {//保存数据指针,传到处理线程request.data = this;}uint32_t id =0;client_t* client = NULL;//把数据接过来进行处理tcp_unit * data = NULL;uv_work_t request;bool error;
}thread_work;

根据我们所定义的协议,如何从包头中取出包体的长度?是第二个字节加上后面四个字节的网络字节序反转成h字节序,就成了包体长度,接下去就是获取包体的过程。

static uint32_t get_bodylen(tcp_settings * setting, char *head)
{//headlen_offset 是偏移量+1int len1 = *(head + 1);char *b = head + 2;return len1+ntohl(*(uint32_t*)b);
}

上一篇里面已经写了一个tcpserver,小有改动,将body里面的内容去除包头,因此tcpunit的数据结构修改了一下:

typedef struct tcp_unit
{//真实数据char * bodydata = NULL;//数据总长度bodylen + headlenint bodylen = 0;//接收到的数据长度int recvlen = 0;//头部长度int headlen = 0;
}tcp_unit;

一切就绪,接下去就是定义一个真正的接收数据的server,从我们第四章里面的tcpserver继承下来:

class tcp_server1 :public tcp_server
{//所有客戶端,用四字节整形数作为hash keystd::unordered_map<uint32_t, client_t*>  v_map_c;uv_mutex_t  _mutex_1;
public:tcp_server1() {}~tcp_server1() {}
protected:uint32_t getid(client_t* client){return 0;/*tcp_settings* cnf = client->config;char* idpos = &client->head[0] + cnf->idoffset;uint32_t deviceid = htonl(*((uint32_t*)idpos));///((deviceid >> 16) & 0xff00) | deviceid >> 24return deviceid;*/}
public:int on_headers_complete(void* param) {//client_t* pclient = (client_t*)param;printf("the header len is %d\n", pclient->recvlen);//printf("the id is %04x\n", getid(pclient));return 0;}//该函数没有进入线程池int on_message_complete(void* param) {client_t* pclient = (client_t*)param;tcp_unit* data = pclient->buffer_data;//char* buf = data->data;//int len = data->tlen;//printf("the total len is %d\n", pclient->buffer_data->tlen);return 0;}//该函数进入线程池int on_data(tcp_unit* data) {//printf("the thread pid is %d\n", _getpid());
#ifdef _DEBUGint hl = data->headlen;//printf("the hl is %d\n", hl);//for (size_t i = hl; i < hl + 8; i++) {//  printf("%02x ", (uint8_t)data->data[i]);//}string test(data->bodydata, data->bodylen);printf("the data is %s\n", test.c_str());//printf("the len is %d\n", data->bodylen);
#endif#if 0//给客户端回送信息tcp_unit_w* unitw = (tcp_unit_w*)malloc(sizeof(tcp_unit_w));unitw->delay = 0;unitw->data = (char*)malloc(sizeof(char) * 18);memcpy(unitw->data, buf, 18);unitw->len = 18;unitw->next = NULL;unitw->type = enum_sc;client_send(rb->id, unitw);//解析成为json发送到相应的接口string response;int timeout = 2; //2秒//post是同步的/*   bool ret = client.Post("http://127.0.0.1:9069/sensor_data/8052", buf, len, response, timeout);if (ret == false) {printf("error!:%s\n", client.geterror().c_str());}printf("response:%s\n", response.c_str());*/
#endifreturn 0;}};

客户端定义

我们后面做sdk的时候,将会分别使用java,node,go,c++,等来做客户端链接,其中又属nodejs是最简单不过的,我们先使用nodejs来做一个客户端:

var net = require('net');
var HOST = '127.0.0.1';
var PORT = 8054;
var client = new net.Socket();var step = 0.01;
function test_8053() {const buftemp = Buffer.allocUnsafe(4 + 2 + 6 + 12);buftemp[0] = 0; //buftemp[1] = 1; //buftemp[2] = 0; //buftemp[3] = 1; //设备编号buftemp[4] = 1;//命令字buftemp[5] = 24;  //包体长度buftemp[6] = 0;// 正常待机,正常下锤探测,第一次首盘探测,过程反复探测,顶部到位反复探测,故障停机buftemp[7] = 0; //故障字buftemp[8] = 1; //警示字1buftemp[9] = 1;//警示字2buftemp[10] = 10; //电池电量buftemp[11] = 0;//备用step += 0.01;buftemp.writeFloatBE(12.90 +step , 12);buftemp.writeFloatBE(13.4 + step, 16);buftemp.writeFloatBE(34.5 +step, 20);client.write(buftemp);setTimeout(test_8053,5000);
}//flv server, 4 bytes length,after is body
var xflag = 0x61;function test_8054() {const buftemp = Buffer.allocUnsafe(19);buftemp[0] = 0;buftemp[1] = 6;//网络字节序一般指大端buftemp.writeInt32BE(7, 2);buftemp.write("qianbo",6);buftemp.write("{a:\"b\"}",12);client.write(buftemp);setTimeout(test_8054, 1000);
}function closesocket() {// client.end();console.log("please close me");
}client.connect(PORT, HOST, function () {console.log('CONNECTED TO: ' + HOST + ':' + PORT);// Write a message to the socket as soon as the client is connected, the server will receive it as message from the client else if (PORT == 8054)test_8054();//setTimeout(test_8053, 1000);
});// Add a 'data' event handler for the client socket
// data is what the server sent to this socket
client.on('data', function (data) {console.log(data);//client.destroy();
});// Add a 'close' event handler for the client socket
client.on('close', function () {console.log('Connection closed');
});

结果:

如下图,我们启动服务器在端口8054等待客户端链接,连接后打印出connected,客户端发送数据后,我们显示出,数据库表名为:qianbo, 数据字段为一个json:{a:“b”}

ok,目前位置,我们将数据传了过去,至于为什么nodejs里面第一个字节为全0,大家可以看我的协议定义,第二个字节长度为6,因为数据库名称长度为6,—>qianbo,.并且根据协议,nodejs的客户端为发布客户端,此次网络实战结束,后面会把接收到的数据存储,以供其他客户端订阅。待续。。。。。。。

如何做一个国产数据库(六) 网络传输 nodejs做测试客户端相关推荐

  1. 如何做一个国产数据库(七) 网络传输 java做订阅客户端

    如何做一个国产数据库一 如何做一个国产数据库二 如何做一个国产数据库三 如何做一个国产数据库四 如何做一个国产数据库五 如何做一个国产数据库六 server端协议定义 再次强调一下我们的protoco ...

  2. 如何做一个国产数据库(三)

    一和二 如何做一个国产数据库一 如何做一个国产数据库二 1.数据结构重新定义 再次重新定义数据结构 typedef struct sdata {uint32_t index;char vardata[ ...

  3. 如何做一个国产数据库(二)

    如果做一个国产数据库一链接 承接上文,继续 1.重新定义数据结构 typedef struct sdata {uint32_t index;char vardata[128]; }sdata;type ...

  4. 如何做一个国产数据库(四)

    网络 这次要用到网络了,存储的时候我们都使用网络来输入输出,当然,像本机是可以使用进程间通信的,不过为了简单,我们此次都使用tcp协议. 协议 此次使用libuv来做网络的传输,我们首先定一个协议,做 ...

  5. 如何做一个国产数据库系统(一)

    做国产数据库之二 做一个国产数据库 做一个数据库系统真的是要懂的是基础,各种基础,网络,文件系统,操作系统,性能,测试,各方面都要懂 使用基本方法 索引文件+数据文件+ B+ 树 ,hash空间 如图 ...

  6. 动手做一个自组网的网络 - 操作系统内核

    动手做一个自组网的网络 - 操作系统内核 动手做一个自组网的网络 - 项目介绍 动手做一个自组网的网络 - 硬件开发板 动手做一个自组网的网络 - 操作系统内核 动手做一个自组网的网络 - 网络协议栈 ...

  7. [VB.NET]想做一个小界面,不知用什么做

    <script type="text/javascript"></script> <script type="text/javascript ...

  8. 想做一个成功的女性,首先要做一个好女人

    第一,我觉得一个好女人,一个真正最后通过一生的努力能够达到一个目标的女人,她是一个幸福的女人.所以说我觉得要做一个好女人.做一个幸福的女人,首先是要做一个有爱的女人. 因为只有爱她才是生命的核心,才是 ...

  9. 同r做一个窗口_怎样在触摸屏上做一个自定义的弹出窗口?

    在触摸屏的应用中,一些故障.警告等提示信息通常是使用系统的报警窗口来实现.系统的报警窗口通常只有故障/警告的编号.日期时间及报警信息等内容,并且可以被折叠.这种千篇一律的报警窗口有时候并不能满足项目的 ...

最新文章

  1. 物联网可应用于十大行业嘛?
  2. 4x4矩阵键盘工作原理及扫描程序_4X4矩形键盘
  3. jqgrid的动态下拉框实现,并解决不能获取值的问题
  4. 使用 Github Actions artifact 在 workflow job 之间共享数据
  5. ubuntu下如何查找某个文件的路径
  6. 【数据结构与算法】排序优化
  7. mysql乐观锁总结和实践 - 青葱岁月 - ITeye博客
  8. vi下的查找替换命令
  9. Python官方中文开发文档
  10. 路由器分类2【按功能级别分】
  11. Eclipse - 取消英文拼写检查
  12. JEECG 3.7.2 专业接口开发版本发布,企业级JAVA快速开发平台
  13. 【ncnn】源码阅读理解(三)——blobs
  14. html table space,html – white-space:nowrap中断显示:table
  15. 反欺诈概念库-信用卡反欺诈管理
  16. mat-icon 翻转_案例研究-翻转网站以获取利润
  17. 【RocketMQ】消息重试、重试次数设置、死信队列
  18. 边缘设备上的计算机视觉
  19. mysql8主从复制集群_mysql8主从复制服务器搭建
  20. 组合数学学习笔记(未完待续

热门文章

  1. 联合概率,条件概率,边缘概率的通俗理解
  2. 一种验证Linux kernel是否可用的Sanity Check方法
  3. 一段可自动点击运行代码(只偷偷的点一次)
  4. 海底捞员工:假笑到脸僵,撑到经理月入20万
  5. 谷歌承诺未来三年将支付10亿美元新闻费用
  6. 小米10超大杯本月亮相稳了:无线快充纪录将再次刷新
  7. 瑞幸咖啡:陆正耀继续担任董事和董事长
  8. 微信上线“拍一拍”功能,结果被网友激情吐槽...
  9. 朋友圈发原图或泄露位置信息?微信回应:系统自动压缩,不会泄露
  10. 双11落下帷幕,天猫、京东战报再创记录,拼多多“失声”...