Java socket编程基础原理学习记录

背景:

  • socket是Java为了简化网络协议操作而抽象成几个简单操作(打开—读/写—关闭)的工具类
  • TCP和UDP两种传输协议,前者可靠占资源,后者只保证大致连贯。
  • socket的协议更加贴合TCP的相关开发,但是也网上也能找到UDP的案例,详情可以参考此https://www.cnblogs.com/zhengtu2015/p/7294477.html
  • 如有错误希望指出

1.TCP/IP简单知识简单介绍

下面是从网络上找到的一个TCP/IP协议的四层模型
初学者可以简单理记忆:快件(应用层)-》中通快递(传输层)-》目的地的地址(网络层)-》快递小哥开始跑腿(链路层)
Java开发一般操作的是应用层和传输层
TCP/IP四层网络模型

大名鼎鼎的三次握手建立链接,其过程如下图,在此过程中双发获取到对方的ip:port(用于准确定位目标)。还有一些其它信息。
在这里插入图片描述

传输过程如何保证包不丢失?

传输简单过程如下,详细过程可自行百度 tcp传输窗口
tcp传输窗口简图
1.信息(文本,文件)传输前会被切割成好多份,每份都有一个编号;
2.接收端会有个虚拟的窗口,譬如窗口大小是4,拿他每次最多能接收四份数据;
3.开始的时候,接收端会把需要接收的编号(1.2.3.4)发给源端,源端就发送这四份数据一起发给接收端
4.如果2号数据先到达,窗口不变,继续等待接收,如果这时1号数据到达,三号未到达,窗口往后移两位,同时请求标号5.6份数据…

四次分手就不说了,有兴趣自行百度

2.Java socket

Java Socket(套接字)通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。
两个socket类——Socket,ServerSocket
使用最频繁的几个方法
Accept方法用于产生"阻塞",监听端口直到有终端连接请求,生成一个响应socket实体。
getInputStream方法获得网络连接输入,用bufferedreader等进行解析。
getOutputStream方法连接的另一端将得到输入,输出给终端。
另外还有超时,校验存活的方法
socket的运行流程
socket的运行流程
两侧都是Java提供的方法,可以看出整个过程中基本上只需要用到上面说到的三个方法即可。
另外,TCP的握手过程是发生在C/S双方生成socket的过程中,并不需要开发人员去实现TCP的复杂过程
例行代码

//服务端
public static void main(String[] args) throws IOException {
    ServerSocket server = new ServerSocket(25,1); //连接请求等待队列只有1,可以在accept前sleep一下,然后用 telnet 127.0.0.1 25 去连接测试
        while (true) {
            Socket socket = server.accept();
            new Thread(() -> { //这里可以使用线程池去优化,主要看自身业务
                System.out.println(socket);
                try (InputStream in = socket.getInputStream()) { //获取输入流
                    System.out.println(socket.getSoTimeout());
//                    socket.setSoTimeout(10000);
                    InputStreamReader inputStreamReader = new InputStreamReader(in);
                    BufferedReader reader = new BufferedReader(inputStreamReader);
                    OutputStream out = socket.getOutputStream();
                    // 重点重点,下面也就read,write,read,write...
                    out.write("220 yyw.cn Esmtp YYW Mail Server\r\n".getBytes());
                    out.flush();
                    String s;
                    while ((s = reader.readLine()) != null) {
                        System.out.println(s);
                        s=s.toLowerCase();
                        if ("quit".equals(s)) {
                            out.write("220 bye\r\n".getBytes());
                            out.flush();
                            break;
                        }
                        switch (s) {
                            case "helo":
                                out.write("250 OK\r\n".getBytes());
                                break;
                            case "auth login" :
                                out.write("334 MailAccount\r\n".getBytes());
                                break;
                        }
                        out.flush();
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    try {
                        socket.close();
                    } catch (IOException e) {
                        e.printStackTrace();
                    }
                }
            }).start();
        }
}
//客户端
    public static void main(String[] args) throws Exception {
        Socket socket = new Socket("127.0.0.1", 25);
        try (InputStreamReader isr = new InputStreamReader(socket.getInputStream())) {
            try (BufferedReader br = new BufferedReader(isr)) {
                String a;
                int i;
                Random r = new Random();
                while ((a = br.readLine()) != null && !"220 bye".equals(a)) {
                    System.out.println(a);
                    OutputStream os = socket.getOutputStream();
                    i = r.nextInt(3) + 1;
                    switch (i) {
                    case 1:
                        os.write("helo\r\n".getBytes());
                        System.out.println("helo");
                        break;
                    case 2:
                        os.write("auth login\r\n".getBytes());
                        System.out.println("auth login");
                        break;
                    default:
                        os.write("quit\r\n".getBytes());
                        System.out.println("quit");
                    }
                    os.flush();
                }
                System.out.println(a);
            }
        } finally {
            socket.close();
        }
    }

参考连接:
https://blog.csdn.net/lvyuan30276/article/details/50458572
https://www.cnblogs.com/mingforyou/p/3258418.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值