Java网络编程 - TCP通信

这篇具有很好参考价值的文章主要介绍了Java网络编程 - TCP通信。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

TCP通信

快速入门(一发一收)

TCP协议回顾:

TCP是一种面向连接,安全、可靠的传输数据的协议

传输前,采用“三次握手”方式,点对点通信,是可靠的

在连接中可进行大数据量的传输

TCP通信模式:

java tcp通信,JavaSE,网络,tcp/ip,java

在java中只要是使用java.net.Socket类实现通信,底层即是使用了TCP协议

编写客户端代码

Socket(客户端):

构造器 说明
Socket(String host , int port) 创建发送端的Socket对象与服务端连接,参数为服务端程序的ip和端口。

Socket类成员方法:

方法 说明
OutputStream getOutputStream() 获得字节输出流对象
InputStream getInputStream() 获得字节输入流对象

客户端实现步骤:

  • 创建客户端的Socket对象,请求与服务端的连接。
  • 使用socket对象调用getOutputStream()方法得到字节输出流。
  • 使用字节输出流完成数据的发送。
  • 不建议直接关闭socket管道释放资源, 一般用户退出时才会关闭。
/**
    客户端
 */
public class ClientDemo {
    public static void main(String[] args) {
        try {
            // 1. 创建socket通信管道请求与服务端进行连接
            /**
                参数一: 服务器IP地址
                参数二: 服务器端口号
             */
            Socket socket = new Socket("127.0.0.1", 7777);

            // 2. 从socket通信管道中获取到字节输出流
            OutputStream os = socket.getOutputStream();
            // 包裹低级字节输出流为字节打印流
            PrintStream ps = new PrintStream(os);

            // 3. 打印流发送消息
            ps.println("我是TCP的客户端");
            ps.flush(); // 刷新
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}
编写服务器代码

ServerSocket(服务端):

构造器 说明
ServerSocket(int port) 注册服务端端口

ServerSocket类成员方法:

方法 说明
Socket accept() 等待接收客户端的Socket通信连接
连接成功返回Socket对象与客户端建立端到端通信

服务端实现步骤:

  • 创建ServerSocket对象,注册服务端端口。
  • 调用ServerSocket对象的accept()方法,等待客户端的连接,并得到Socket管道对象。
  • 通过Socket对象调用getInputStream()方法得到字节输入流、完成数据的接收。
  • 不建议直接关闭socket管道释放资源, 一般用户退出时才会关闭。
/**
    服务器
 */
public class ServerDemo {
    public static void main(String[] args) {
        try {
            // 1. 创建ServerSocket对象注册服务器端口
            ServerSocket serverSocket = new ServerSocket(7777);

            // 2. 调用accept方法, 等待客户端连接, 连接成功返回socket管道对象
            Socket socket = serverSocket.accept();

            // 3. 从socket管道中获取字节输入流, 完成数据接受
            InputStream is = socket.getInputStream();
            // 把字节输入流包装为缓冲字符输入流进行消息接收
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            // 按照行读取
            String message;
            if ((message = br.readLine()) != null) {
                System.out.println(message);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

多发多收

需求

  • 使用TCP通信方式实现:多发多收消息。

具体要求

  • 可以使用死循环控制服务端收完消息继续等待接收下一个消息。
  • 客户端也可以使用死循环等待用户不断输入消息。
  • 客户端一旦输入了exit,则关闭客户端程序,并释放资源。

客户端

/**
    客户端
 */
public class ClientDemo {
    public static void main(String[] args) {
        try {
            Socket socket = new Socket("127.0.0.1", 7777);

            OutputStream os = socket.getOutputStream();
            PrintStream ps = new PrintStream(os);

            // 客户端使用死循环等待用户不断地输入消息
            Scanner scanner = new Scanner(System.in);
            while (true) {
                System.out.println("发送消息: ");
                String inp = scanner.nextLine();
                // 一旦输入了exit,则关闭客户端程序,并释放资源
                if (inp.equals("exit")) {
                    System.out.println("下线成功");
                    ps.close();
                    break;
                }
                ps.println(inp);
                ps.flush();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

服务端

/**
    服务器
 */
public class ServerDemo {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(7777);

            Socket socket = serverSocket.accept();

            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String message;
            // 死循环控制服务端收完消息继续等待接收下一个消息
            while ((message = br.readLine()) != null) {
                System.out.println("收到消息: " + message);
            }

        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

多发多收(同时接受多个客户端)

思考: 案例实现了多发多收,那么是否可以同时接收多个客户端的消息?

不可以的。

因为服务端现在只有一个线程,只能与一个客户端进行通信; 并且上面代码中, 我们只连接了一个客户端然后就在死循环接受消息。

那么如何才可以让服务端可以处理多个客户端的通信需求

引入多线程。

同时处理多个客户端消息实现架构如下:

主线程死循环不断地接收socket链接, 每成功链接一个socket, 就交给子线程处理

java tcp通信,JavaSE,网络,tcp/ip,java

实现步骤如下:

优化服务器代码即可

创建一个线程类, 用来处理接收消息

public class ServerReaderThread extends Thread {
    private Socket socket;
    public ServerReaderThread(Socket socket) {
        this.socket = socket;
    }
    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String message;
            // 死循环控制服务端收完消息继续等待接收下一个消息
            while ((message = br.readLine()) != null) {
                System.out.println("收到消息: " + message);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

在服务器主线程中, 每链接到一个socket都要创建一个线程类交给子线程处理

/**
    服务器
 */
public class ServerDemo {
    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(7777);
            // 1. 主线程中定义一个死循环由主线程不断地接收客户端socket管道连接
            while (true) {
                // 2. 每接收到一个socket管道, 都交给一个独立的子线程负责读取消息
                Socket socket = serverSocket.accept();
                // 交给子线程处理, 并启动子线程
                new ServerReaderThread(socket).start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

线程池优化

目前的通信架构存在什么问题

客户端与服务端的线程模型是: 1-1的关系, 有多少客户端就会创建多少线程。

客户端并发越多,系统瘫痪的越快。

引入线程池处理多个客户端消息的架构如下:

java tcp通信,JavaSE,网络,tcp/ip,java

线程池优化多发多收, 我们只需要优化服务器的代码即可:

创建一个Runnable任务类

public class ServerReaderRunnable implements Runnable {
    private Socket socket;
    public ServerReaderRunnable(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {
        try {
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));

            String message;
            // 死循环控制服务端收完消息继续等待接收下一个消息
            while ((message = br.readLine()) != null) {
                System.out.println(socket.getRemoteSocketAddress() + "收到消息: " + message);
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }
}

优化服务器端代码

/**
    服务器
 */
public class ServerDemo {
    // 使用静态变量记录一个线程池对象
    private static ExecutorService pool = new ThreadPoolExecutor(3, 5, 6,
            TimeUnit.SECONDS, new ArrayBlockingQueue<>(2), Executors.defaultThreadFactory(),
            new ThreadPoolExecutor.AbortPolicy());

    public static void main(String[] args) {
        try {
            ServerSocket serverSocket = new ServerSocket(7777);
            while (true) {
                Socket socket = serverSocket.accept();
                System.out.println(socket.getRemoteSocketAddress() + "上线了");
                // 创建Runnable任务交给线程池处理
                pool.execute(new ServerReaderRunnable(socket));
            }
        } catch (Exception e) {
            e.printStackTrace();
        }

    }
}

线程池优势是什么?

服务端可以复用线程处理多个客户端,可以避免系统瘫痪。

适合客户端通信时长较短的场景。
计思想, 客户端将消息发送给服务器, 再由服务器进行转发给其他客户端。文章来源地址https://www.toymoban.com/news/detail-804939.html

到了这里,关于Java网络编程 - TCP通信的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Java【网络编程2】使用 TCP 的 Socket API 实现客户端服务器通信(保姆级教学, 附代码)

    📕各位读者好, 我是小陈, 这是我的个人主页 📗小陈还在持续努力学习编程, 努力通过博客输出所学知识 📘如果本篇对你有帮助, 烦请点赞关注支持一波, 感激不尽 📙 希望我的专栏能够帮助到你: JavaSE基础: 基础语法, 类和对象, 封装继承多态, 接口, 综合小练习图书管理系统

    2024年02月05日
    浏览(65)
  • Java网络编程(UDP、TCP)

    在网络通信协议下,不同计算机上运行的程序,进行的数据传输。 应用场景:即时通信、网游对战、金融证券、国际贸易、邮件、等等。 不管是什么场景,都是计算机跟计算机之间通过网络进行数据传输。 Java中可以使用java.net包下的技术轻松开发出常见的网络应用程序。

    2024年02月05日
    浏览(63)
  • 【Java学习笔记】 68 - 网络——TCP编程、UDP编程

    https://github.com/yinhai1114/Java_Learning_Code/tree/main/IDEA_Chapter21/src 目录 项目代码 网络 一、网络相关概念 1.网络通讯 2.网络 3.IP地址 4.域名 5.端口号 6.网络通讯协议 TCP协议:传输控制协议 UDP协议: 二、InetAddress类 1.相关方法 三、Socket 1.基本介绍 2.TCP网络通信编程 基本介绍 应用案例

    2024年02月04日
    浏览(53)
  • Java网络编程 *TCP与UDP协议*

    把分布在 不同地理区域 的具有独立功能的计算机, 通过通信设备与线路 连接起来,由功能完善的软件实现资源共享和信息传递的 系统 简单来说就是把不同地区的计算机通过设备连接起来,实现不同地区之前的数据传输 网络编程 是借助计算机网络,实现我们所写的程序,在不同

    2024年01月16日
    浏览(58)
  • Java网络编程(二)Socket 套接字(TCP和UDP),以及TCP的回显

    我们软件工作者,着重编写的是应用层的代码,但是发送这个数据,我们就需要将应用层传输到传输层,也就意味着我们需要调用应用层的API,统称为 Socket API。 套接字的分类: 流套接字:使用传输层TCP协议 特点: 有连接:使用 TCP 通信的双方,需要时刻保存对方的相关消

    2024年02月09日
    浏览(54)
  • 【Java网络编程】OSI七层网络模型与TCP/IP协议簇

    1.1、OSI七层网络模型 OSI七层网络模型中,每层的功能如下: 应用层:人与计算机网络交互的窗口。 表示层:负责数据格式的封装,如加密、压缩、编解码等。 会话层:建立、终止、管理不同端间的会话连接。 传输层:提供端到端(两台机器)之间的传输机制,以及提供流

    2024年04月11日
    浏览(48)
  • .NET网络编程——TCP通信

            就是将不同区域的电脑连接到一起,组成局域网、城域网或广域网。把分部在不同地理区域的计算机于专门的外部设备用通信线路 互联成一个规模大、功能强的网络系统,从而使众多的计算机可以方便地互相传递信息,共享硬件、软件、数据信息等资源。       

    2024年02月16日
    浏览(47)
  • Java网络编程基础:TCP Socket套接字编程 IntAddress UDP等...

    目录 一,网络基础 1.IP地址 2.端口 3.TCP/UDP协议 4.网络编程开发模式  二,基于套接字的Java网络编程 1.Socket  2.InetAddress 三.基于TCP的Socket网络编程 1.单服务器端与单Socket客户端一次通讯 2.单服务器端接收多次通讯  3.TCP网络通讯补充 四,基于UDP的网络编程 1. DatagramSocket:收发

    2024年04月29日
    浏览(46)
  • Java中的网络编程------基于Socket的TCP编程和基于UDP的网络编程,netstat指令

    Socket 在Java中,Socket是一种用于网络通信的编程接口, 它允许不同计算机之间的程序进行数据交换和通信 。Socket使得网络应用程序能够通过TCP或UDP协议在不同主机之间建立连接、发送数据和接收数据。以下是Socket的基本介绍: Socket类型 :在Java中,有两种主要类型的Socket,分

    2024年02月10日
    浏览(39)
  • 【Java EE初阶十五】网络编程TCP/IP协议(二)

            tcp的socket api和U大片的socket api差异很大,但是和前面所讲的文件操作很密切的联系         下面主要讲解两个关键的类:         1、ServerSocket:给服务器使用的类,使用这个类来绑定端口号         2、Socket:即会给服务器使用,又会给客户端使用;         

    2024年02月20日
    浏览(51)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包