Java 网络NIO学习笔记--多线程的NIO Java TCP服务示例

Publish: March 16, 2021 Category: 代码分享 No Comments

Java NIO中涉及的基础内容:

1 基本概念

  • Channel 通道

Channel 通道,类似于流一个channel可以和文件或者网络socket对应,以对应socket为例,往Channel中写数据等同于往Socket中写入数据。

  • Buffer 缓冲区

类似于一块内存区域或者字节数组,在NIO的使用中只有将数据打包成Buffer形式才能往Channel写入或者读取数据。

  • Selector 选择器

Selector是一个Channel管理器,可以由一个线程管理,可以管理多个Channel对象,也就是对应的网络socket。

2 方法原理
SelectableChannel 是一个Channel的类实现,表示被选择通道,任何一个SelectableChannel都可以将自己注册到Selector中,这个Channel就能被Selector管理,与客户端连接的数据没有准备好时候,Selector会处于等待状态,当SelectableChannel的数据准备好时,Selector就会接到通知,得到那些已经准备好的数据。


阅读剩余部分...

Java 网络NIO学习笔记--多线程的阻塞式Java TCP服务示例

Publish: March 16, 2021 Category: 代码分享 No Comments

Java NIO中涉及的基础内容:

  • Channel 通道
  • Buffer 缓冲区
  • File IO 文件IO
  • Network IO 网络IO

最简单的基于Socket的服务端多线程模型,服务器为每一个客户端派发一个线程,新的线程只负责单独的客户端数据。为了接受客户端连接,服务端会有一个单独的派发线程。

package testnio;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

/**
 * 多线程的Java TCP服务示例
 */
public class MultiThreadEchoServer {
    //可缓存线程池 用来处理每一个客户端
    private static ExecutorService tp = Executors.newCachedThreadPool();

    /**
     * 内部类,负责创建线程并处理socket数据
     */
    static class HandleMsg implements Runnable{

        //读取Socket内容并返回
        Socket serverSocket;
        public HandleMsg(Socket serverSocket){
            this.serverSocket = serverSocket;
        }

        @Override
        public void run() {
            BufferedReader inStream = null;
            PrintWriter outStream = null;

            try {
                inStream = new BufferedReader(new InputStreamReader(serverSocket.getInputStream()));
                outStream = new PrintWriter(serverSocket.getOutputStream(), true);
                String inputLine = null;
                //处理客户端请求
                long b = System.currentTimeMillis();
                while ((inputLine = inStream.readLine()) != null){
                    outStream.println(inputLine);
                }
                long e = System.currentTimeMillis();
                System.out.println("spend:" + (e-b)+"ms");

            } catch (IOException e) {
                e.printStackTrace();
            }finally {
                try {
                    if (inStream != null) inStream.close();
                    if (outStream != null) outStream.close();
                    serverSocket.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }

        }

    }

    /**
     * 入口方法,根据连接创建新的处理线程和服务端Socket来处理业务
     * @param args
     */
    public static void main(String[] args) {
        ServerSocket echoServer = null;
        Socket serverSocket = null;

        try {
            echoServer = new ServerSocket(8001);
        } catch (IOException e) {
            e.printStackTrace();
        }

        while (true){
            try {
                //accept()方法会一致阻塞在这里,直到新的客户端连接到来
                serverSocket = echoServer.accept();
                System.out.println(serverSocket.getRemoteSocketAddress() + " connect!");
                tp.execute(new HandleMsg(serverSocket));
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }


}

阅读剩余部分...

PHP的InfluxDB客户端库使用

Publish: October 16, 2020 Category: 代码分享 No Comments

这是一个influxdb的1.新版本客户端
https://github.com/influxdata/influxdb-php
如果使用的是2.x版本,请使用找个客户端
https://github.com/influxdata/influxdb-client-php

概览

一个易于使用的库,用于将inflexdb与PHP结合使用。由 @thecodeassassin, @gianarb. 维护。inflexdbphp库是为了拥有python influxdb客户机的php端口而创建的。这样,不同编程语言之间将有一个通用的抽象库。

安装

可以使用composer完成安装:

$ composer require influxdb/influxdb-php

PHP 5.3 和 PHP 5.4 用户请zhu'yi
如果使用php5.3和php5.4,0.1.x版本仍然受支持(bug修复和新版本修复)。0.1.x分支将在php5.3和php5.4上运行,但不包含1.0.0版本所具有的所有特性,例如UDP支持。

开始使用

初始化一个新的客户端对象

$client = new InfluxDB\Client($host, $port);

这将创建一个新的客户机对象,您可以使用它来读写InfluxDB的点。还可以从DSN(数据源名称)创建客户端:

// 直接获取数据库句柄
$database = InfluxDB\Client::fromDSN(sprintf('influxdb://user:pass@%s:%s/%s', $host, $port, $dbname));

// 使用客户端检索其他数据库
$client = $database->getClient();

重要提示:当使用DSN时,不要忘记urlencode()password(和username),尤其是当它包含非字母数字字符时。不这样做可能会引发异常。





阅读剩余部分...

MySQL基于距离半径的搜索和区域搜索POI实践

Publish: June 8, 2020 Category: 小技巧,代码分享 No Comments

因为应用是基于MySql的,所以我们的技术选型也是主要有两种:一种是多边形是否包含,一种是对每一个点进行计算。

首先看第一种:区域内搜索

在我们的业务平台中有很多景区的,每个景区都有围栏地址和中心点地址,我从中摘录一部分,这次重点关注fence_center也就是中心点字段。
我们的table定义如下:

CREATE TABLE `map` (
 `id` int(11) NOT NULL,
 `name` varchar(32) COLLATE utf8_unicode_ci NOT NULL COMMENT '景区名称',
 `fence_center` point DEFAULT NULL,
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci COMMENT='景区表';

我先确定一个多边形围栏,然后直接查找在围栏内的点。这样的计算有一个问题,就是必须事先知道多边形区域,这种方式更适合按区域查找场景。


阅读剩余部分...

MySQL地理围栏数据处理实践

Publish: April 15, 2020 Category: 编程,代码分享 1 Comment

我们本次实践的主要内容

  • 地理围栏数据构建
  • mysql 如何使用geo相关字段类型
  • 围栏算法计算

地理围栏数据构建

使用DDL创建一个数据库模式:

CREATE TABLE `geo_1` (
  `id` int(11) NOT NULL AUTO_INCREMENT,
  `fence_point` point NOT NULL COMMENT '中心点',
  `fence_polygon` polygon NOT NULL COMMENT '单个围栏',
  `fence_multipolygon` multipolygon NOT NULL COMMENT '多围栏',
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4

使用原生sql语句插入几条数据

INSERT INTO `geo_1`(
    `id`,
    `fence_point`,
    `fence_polygon`,
    `fence_multipolygon`
)
VALUES(
    NULL,
    GEOMFROMTEXT('POINT(117.134516 36.672215)'),
    GEOMFROMTEXT(
        'POLYGON((117.147711 36.692958,117.152174 36.664804,117.120588 36.659434,117.116297 36.678848,117.147711 36.692958))'
    ),
    GEOMFROMTEXT(
        'MULTIPOLYGON(((117.143528 36.678686,117.144215 36.676758,117.142927 36.67669,117.142412 36.677997,117.143528 36.678686)),((117.144837 36.675829,117.144794 36.674487,117.143743 36.674659,117.14385 36.675881,117.144837 36.675829)),((117.127574 36.670235,117.124227 36.668858,117.124785 36.666448,117.13075 36.667412,117.127574 36.670235)))'
    )
);

特别要注意的几点:

  • POINT类型是单个点,构建只需要一个POINT类型数据即可
  • POLYGON类型或者MULTIPOLYGON中的数据必须是首位相连,也就是第一组数据和最后一组数据是相同的,以构成一个闭合的多边形。

阅读剩余部分...