高并发基础之Socket入门

在这里插入图片描述

1 问题背景

毕业设计做高并发相关的研究,前面粗略研究了解决高并发的核心——LinuxIO模型,笔者认为需要再粗略研究Socket相关的问题。

参考自:Socket技术详解(看清Socket编程)

2 什么是Socket

计算机之间通信需要知道对方的地址,Socket就是存储这个地址,实质上Socket是IP加端口号,格式是xx.xx.xx.xx:xxxx。如下图所示:
在这里插入图片描述
Socket可以理解成处于应用层与传输层之间。类比传输层的TCP三次握手,Socket也有三次握手,介绍Socket三次握手之前,先回顾TCP的三次握手。

3 TCP的三次握手

模型图如下:

在这里插入图片描述
如上图所示,客户端A主动发送SYB数据包,服务端B接收到后发送确认给A,A收到后对此确认发送确认数据包,A的连接建立了,B收到确认后也建立了连接。

4 Socket三次握手

4.1 模型概览

模型图如下:

在这里插入图片描述

4.2 具体函数

此处给出客户端单向发送数据给服务端为例子讲解。双向通信的例子还未研究。本以为双向通信很简单,然而写玩代码做测试的时候才发现没有想象中那么容易。

在这里插入图片描述

5 客户端单向通信服务端例子

场景:使用BIO方式实现,服务端监听客户端发来的连接请求,启动子线程处理客户端发来的信息。参考自B站的尚硅谷Netty教学视频

@Slf4j
public class BioServer {

    public static void main(String[] args) {
        // 阿里开发规范必须指定参数来构造线程池
        ThreadPoolExecutor serverPoolExecutor = new ThreadPoolExecutor(10,
                20,
                10,
                TimeUnit.MINUTES,
                new LinkedBlockingDeque<>(10),
                new DefaultThreadFactory("server-pool"));
        // 服务端创建socket
        try {
            ServerSocket serverSocket = new ServerSocket(8099);
            log.info("服务端已启动");

            while (true) {
                log.info("服务端等待连接");
                Socket socket = serverSocket.accept();
                log.info("主线程" + Thread.currentThread().getId() + "接收到一个客户端请求连接");
                // 创建线程池,启动一个线程去与客户端通信
                serverPoolExecutor.execute(new Runnable() {
                    @Override
                    public void run() {
                        // 处理客户端的信息
                        handler(socket);
                    }
                });
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static void handler(Socket socket) {
        try{
            // 存储客户端发来的信息
            byte[] bytes = new byte[1024];
            InputStream inputStream = socket.getInputStream();
            while (true) {
                log.info("等待客户端发来数据...");
                // 从socket中读取发来的信息
                int read = inputStream.read(bytes);
                if (read != -1) {
                    // 输出客户端发来的信息
                    log.info("线程" + Thread.currentThread().getId() + "接收到数据:" + new String(bytes, 0, read));
                } else {
                    break;
                }
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            // 关闭与客户端的连接
            try {
                socket.close();
                log.info("客户端已关闭连接");
            } catch (IOException e) {
                e.printStackTrace();
            }
        }

    }
}

使用telnet命令模拟客户端,ip和端口号是根据上面代码中的来的。输入telnet 127.0.0.1 8099。即可连接到服务端,按ctrl + ]可以进入发送数据的状态,使用send xxx命令发送数据。如下:

在这里插入图片描述

在这里插入图片描述

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值