Java 通过实现简单的TCP通信程序来理解TCP通信

概述

TCP通信能实现两台计算机之间的数据交互,通信的两端,要严格区分为客户端(Client)与服务端(Server)。

两端通信的步骤

  1. 服务端程序,需要事先启动,等待客户端的连接。
  2. 客户端主动连接服务器端,连接成功才能通信。服务端不可以主动连接客户端。

在Java中,提供了两个类用于实现TCP通信程序:

  1. 客户端:java.net.Socket类表示。创建Socket对象,向服务端发出连接请求,服务端响应请求,两者建立连接开始通信。
  2. 服务端:java.net.ServerSocket类表示。创建ServerSocket对象,相当于开启一个服务,并等待客户端的连接。

如下图:

客户端1和服务端进行一个通讯的交互①②③④,需要四个IO流对象,客户端2也是如此。那么两个客户端都和同一个服务端进行交互,服务端怎么区分呢?在服务器端有一个accept方法,可以获取到请求的客户端对象。

多个客户端同时和服务器进行交互,就需要使用多个IO流对象。服务器是没有IO流的,服务器可以获取到请求的客户端Socket对象t,使用每个客户端Socket中提供的IO流和客户端进行交互。服务器使用客户端的字节输入流读取客户端发送的数据,使用客户端的字节输出流给客户端回写数据。简单的说,就是服务器使用客户端的流和客户端交互。

Socket类

Socket类:该类实现客户端套接字,套接字指的是两台设备之间通讯的端点。

构造方法

public Socket(String host, int port)
// 创建套接字对象(两台设备之间通讯的端点对象)并将其连接到指定主机上的指定端
// 口号。如果指定的host是null,则相当于指定地址为回送地址。
  1. 套接字:包含了IP地址(host)和端口号(port)的网络单位。
  2. 回送地址:回送地址(127.x.x.x)是本机回送地址(Loopback Address),主要用于网络软件测试以及本地机进程间通信,无论什么程序,一旦使用回送地址发送数据,立即返回,不进行任何网络传输。

成员方法

OutputStream getOutputStream()
// 返回此套接字的输出流。

InputStream getInputStream()
// 返回此套接字的输入流

void close()
// 关闭此套接字。

举例

使用Java程序,进行客户端和服务端之间的通信。

TCP通讯的客户端

向服务器发送连接请求,给服务器发送数据,读取服务器回写的数据。

实现步骤:

1.创建一个客户端对象Socket,构造方法中绑定服务器的IP地址和端口号。
2.使用Socket对象中的方法getOutputStream(),获取网络字节输出流OutputStream对象。
3.使用网络字节输出流OutputStream对象中的方法write,给服务器发送数据。
4.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象。
5.使用网络字节输入流InputStream对象中的方法read,读取服务器回写的数据。
6.释放资源(Socket)。

注意:

1.客户端和服务器端进行交互,必须使用Socket中提供的网络流,不能使用自己创建的流对象。
2.当我们创建客户端对象Socket的时候,就会去请求服务器和服务器经过3次握手建立连接通路。这时如果服务器没有启动,那么就会抛出异常(ConnectException: Connection refused: connect)。
如果服务器已经启动,那么就可以进行交互了。

客户端代码实现:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;

public class TcpClient {
    public static void main(String[] args) throws IOException {
        method();
    }

    private static void method() throws IOException {
        // 创建一个客户端对象Socket,构造方法中绑定服务器的IP地址和端口号。
        Socket socket = new Socket("127.0.0.1", 8888);

        // 使用Socket对象中的方法getOutputStream(),获取网络字节输出流OutputStream对象。
        OutputStream outputStream = socket.getOutputStream();

        // 使用网络字节输出流OutputStream对象中的方法write,给服务器发送数据。
        outputStream.write("你好吖!服务器。".getBytes());

        // 使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象。
        InputStream  inputStream = socket.getInputStream();

        // 使用网络字节输入流InputStream对象中的方法read,读取服务器回写的数据。
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);
        System.out.println(new String(bytes, 0, len));

        // 释放资源(Socket)。
        socket.close();
    }
}

完成了客户端代码的编写后,先了解一下ServerSocket类,然后编写服务端Java代码。 

ServerSocket类

ServerSocket类:此类现服务器套接字。服务器等待请求通过网络传入。它基于该请求执行某些操作,然后可能向请求者返回结果。

构造方法

ServerSocket(int port)
// 创建绑定到特定端口的服务器套接字。

成员方法

Socket accept()
// 侦听并接受到此套接字的连接。

服务器端必须明确一件事情,必须的知道是哪个客户端请求的服务器,所以可以使用accept方法获取到请求的客户端对象Socket。

举例

接收客户端的请求,读取客户端发送的数据,给客户端回写数据。

TCP通信的服务端

实现步骤:

1.创建服务器ServerSocket对象,对象中传递系统要指定的端口号。
2.使用ServerSocket对象中的方法accept,获取到请求的客户端对象Socket。
3.使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象。
4.使用网络字节输入流InputStream对象中的方法read,读取客户端发送的数据。
5.使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象。
6.使用网络字节输出流OutputStream对象中的方法write,给客户端回写数据。
7.释放资源(Socket,ServerSocket)。

服务端代码实现:

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class TcpServer {
    public static void main(String[] args) throws IOException {
        method();
    }

    private static void method() throws IOException {
        // 创建服务器ServerSocket对象,对象中传递系统要指定的端口号。
        ServerSocket serverSocket = new ServerSocket(8888);

        // 使用ServerSocket对象中的方法accept,获取到请求的客户端对象Socket。
        Socket socket = serverSocket.accept();

        // 使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象。
        InputStream inputStream = socket.getInputStream();

        // 使用网络字节输入流InputStream对象中的方法read,读取客户端发送的数据。
        byte[] bytes = new byte[1024];
        int len = inputStream.read(bytes);
        System.out.println(new String(bytes, 0, len));

        // 使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象。
        OutputStream outputStream = socket.getOutputStream();

        // 使用网络字节输出流OutputStream对象中的方法write,给客户端回写数据。
        outputStream.write("收到,谢谢!".getBytes());

        // 释放资源(Socket,ServerSocket)。
        socket.close();
        serverSocket.close();
    }
}

客户端程序和服务端程序都已经编写完成,先运行服务端程序,然后再运行客户端程序。

客户端程序:控制台输出(收到来自服务端回写的数据)

收到,谢谢您!客户端。

服务端程序:控制台输出(接收到客户端发来的请求数据)

你好吖!服务器。

输出截图如下:

客户端程序和服务端程序对比(4K图,可放大):

代码实现步骤:

  1. 第一步

    服务器端:
    
    // 创建服务器ServerSocket对象,对象中传递系统要指定的端口号。
    ServerSocket serverSocket = new ServerSocket(8888);
    
    // 使用ServerSocket对象中的方法accept,获取到请求的客户端对象Socket。
    Socket socket = serverSocket.accept();
  2. 第二步

    客户端:
    
    // 创建一个客户端对象Socket,构造方法中绑定服务器的IP地址和端口号。
    Socket socket = new Socket("127.0.0.1", 8888);
    
    // 使用Socket对象中的方法getOutputStream(),获取网络字节输出流OutputStream对象。
    OutputStream outputStream = socket.getOutputStream();
    
    // 使用网络字节输出流OutputStream对象中的方法write,给服务器发送数据。
    outputStream.write("你好吖!服务器。".getBytes());
  3. 第三步

    服务器端:
    
    // 使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象。
    InputStream inputStream = socket.getInputStream();
    
    // 使用网络字节输入流InputStream对象中的方法read,读取客户端发送的数据。
    byte[] bytes = new byte[1024];
    int len = inputStream.read(bytes);
    System.out.println(new String(bytes, 0, len));
    
    // 使用Socket对象中的方法getOutputStream()获取网络字节输出流OutputStream对象。
    OutputStream outputStream = socket.getOutputStream();
    
    // 使用网络字节输出流OutputStream对象中的方法write,给客户端回写数据。
    outputStream.write("收到,谢谢您!客户端。".getBytes());
  4. 第四步

    客户端:
    
    // 使用Socket对象中的方法getInputStream()获取网络字节输入流InputStream对象。
    InputStream  inputStream = socket.getInputStream();
    
    // 使用网络字节输入流InputStream对象中的方法read,读取服务器回写的数据。
    byte[] bytes = new byte[1024];
    int len = inputStream.read(bytes);
    System.out.println(new String(bytes, 0, len));
  5. 第五步

    客户端:
    // 释放资源(Socket)。
    socket.close();
  6. 第六步

    服务器端:
    
    // 释放资源(Socket,ServerSocket)。
    socket.close();
    serverSocket.close();

原文地址:https://www.cnblogs.com/liyihua/p/12275417.html

时间: 2024-08-07 17:01:48

Java 通过实现简单的TCP通信程序来理解TCP通信的相关文章

Java实现一个简单的网络聊天程序

一.TCP通信概述 TCP协议是面向连接的通信协议,在传输数据之前,发送端和接收端必须建立逻辑连接,然后再传输数据,它提供了两台计算机之间可靠无差错的数据传输. 在TCP连接中必须要明确客户端与服务器端,由客户端向服务端发出连接请求,每次连接的创建都需要经过三次握手. 三次握手:TCP协议中,在发送数据的准备阶段,客户端与服务器之间的三次交互,以保证连接的可靠. ·第一次握手,客户端向服务器端发出连接请求,等待服务器确认. ·第二次握手,服务器端向客户端回送一个响应,通知客户端收到了连接请求.

用java写一个简单的文件拷贝程序吧

代码: public static void copyFile(String srcPath, String destPath) throws IOException { //建立File对象的来源与目的 File src = new File(srcPath); File dest = new File(destPath); //由于只能拷贝文件,所以判定输入流是否为文件 if(!src.isFile()) { System.out.println("只能拷贝文件!"); throw

使用Boost.Asio编写通信程序

摘要:本文通过形像而活泼的语言简单地介绍了Boost::asio库的使用,作为asio的一个入门介绍是非常合适的,可以给人一种新鲜的感觉,同时也能让体验到asio的主要内容. Boost.Asio是一个跨平台的网络及底层IO的C++编程库,它使用现代C++手法实现了统一的异步调用模型. ASIO的同步方式 ASIO库能够使用TCP.UDP.ICMP.串口来发送/接收数据,下面先介绍TCP协议的读写操作.对于读写方式,ASIO支持同步和异步两种方式,首先登场的是同步方式,下面请同步方式自我介绍一下

理解TCP和UDP协议

目录 TCP 协议 UDP协议 TCP和UDP的区别 TCP和UDP的使用场景 一 TCP协议 1.TCP的头部格式 理解TCP协议,首要的就是TCP协议的头部格式 ·        Source Port和Destination Port:分别占用16位,表示源端口号和目的端口号:用于区别主机中的不同进程,而IP地址是用来区分不同的主机的,源端口号和目的端口号配合上IP首部中的源IP地址和目的IP地址就能唯一的确定一个TCP连接: ·        Sequence Number:用来标识从T

基于TCP协议的java单线程通信程序

这是大二学JAVA基础时写的一个小程序,通过在程序中设置主机IP和端口实现两台主机间的通信.由于当时对JAVA编程的规范掌握的不是很好, 所以程序界面设计代码和通信模块代码都放在了同一个类中. 类一:服务器端的代码 import java.awt.BorderLayout;import java.awt.Container;import java.awt.event.ActionEvent;import java.awt.event.ActionListener;import java.io.B

利用java的Socket实现一个简单hello/hi聊天程序

利用java的Socket实现一个简单hello/hi聊天程序 首先,我们来用java实现一个简单的hello/hi聊天程序.在这个程序里,我学习到了怎么用socket套接套接字来进行编程.简单理解了一些关于socket套接字和底层调用的关系.关于java的封装思想,我学会了一些东西,java里真的是万物皆对象.还学到了一点多线程的知识. TCP 在这里,不得不先介绍以下TCP.TCP是传输层面向连接的协议.提供了端到端的进程之间的通信方式.TCP在通信之前要先建立连接.这里我们称这个建立连接的

Java实现一个hello/hi的简单的网络聊天程序

使用Java的Socket实现客户端和服务器端之间的连接,实现客户端重复发送数据到服务器端的功能.即,用户可以在控制台不断输入内容,并将内容逐一发送给服务端.并在服务端显示. socket定义 网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket.建立网络通信连接至少要一对端口号(socket).socket本质是编程接口(API),对TCP/IP的封装,TCP/IP也要提供可供程序员做网络开发所用的接口,这就是Socket编程接口;HTTP是轿车,提供了封装

java实现hello/hi的简单的网络聊天程序与ServerSocket调用栈跟踪

java实现hello/hi的简单的网络聊天程序 网络聊天采用TCP协议通过java实现 import java.io.*; import java.net.Socket; public class Client { public static void main(String[] args) throws Exception{ Socket socket = new Socket("192.168.31.68", 6666); BufferedReader reader = new

JAVA学习第六十课 — UDP协议 &基于多线程模拟简单的QQ聊天程序

UDP传输 UDP有发送端和接受端,有两大类,DatagramSocket.DatagramPacket 建立发送端和接收端 建立数据包 调用Socket的接收发送方法 关闭Socket 注意:发送端和接收端是两个独立的运行程序 UDP发送端演示 DatagramPacket(byte[] buf, int length, InetAddress address, int port) 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号. public static voi