Java Socket编程之基于TCP协议通信

1.说明

Socket(套接字)是计算机网络编程中用于实现网络通信的一种编程接口或抽象概念。
它提供了一种标准的接口,使应用程序能够通过网络与其他计算机进行通信。
Socket可以看作是应用程序与网络之间的一个通信端点,类似于电话中的插座。
通过Socket,应用程序可以创建、连接、发送和接收数据,以实现网络通信。
Socket通常使用TCP/IP协议栈作为底层网络协议,
但也可以与其他协议一起使用,
如UDP(User Datagram Protocol)和ICMP(Internet Control Message Protocol)等。

Java中基于TCP协议实现网络通信的类

  • 客户端的Socket类
  • 服务器端的ServerSocket类

Java Socket编程之基于TCP协议通信_第1张图片

服务端和客户端使用Socket通信的步骤:

  1. 创建ServerSocket和Socket
  2. 打开连接到Socket的输入/输出流
  3. 按照协议对Socket进行读/写操作
  4. 关闭输入输出流、关闭Socket

2.服务端编程

服务端使用ServerSocket编程步骤:

  1. 创建ServerSocket对象,绑定监听端口
  2. 通过accept()方法监听客户端请求
  3. 连接建立后,通过输入流读取客户端发送的请求信息
  4. 通过输出流向客户端发送乡音信息
  5. 关闭相关资源
package edu.java.net.socket.tcp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * TCP Socket 套接字服务端
 */
public class ServerSocketDemo {
    public static void main(String[] args) throws Exception {
        // simpleServer();
        concurrentServer();
    }

    /**
     * 单线程服务端,只能接收一个客户端的请求,并且会话结束后服务端自动停止
     */
    public static void simpleServer() throws IOException {
        // 基于TCP协议的Socket通信,实现用户登录,服务端

        // 1.创建一个服务器端Socket,即ServerSocket,指定绑定的端口,并监听此端口
        // 1024-65535的某个端口
        ServerSocket serverSocket = new ServerSocket(10086);
        System.out.println("服务端已经启动,等待客户端的连接...");
        // 2.调用accept()方法开始监听,等待客户端的连接
        // 进程阻塞直到接收到客户端请求
        Socket socket = serverSocket.accept();

        // 3.获取输出流,响应客户端的请求
        OutputStream os = socket.getOutputStream();
        PrintWriter pw = new PrintWriter(os);
        pw.write("欢迎您访问服务端!" + System.lineSeparator());
        pw.flush();

        // 4.获取输入流,并读取客户端信息
        InputStream is = socket.getInputStream();

        InputStreamReader isr = new InputStreamReader(is);
        BufferedReader br = new BufferedReader(isr);
        String info = null;
        while ((info = br.readLine()) != null) {
            System.out.println("服务端接收到消息:" + info);
            pw.write("服务端收到:" + info + System.lineSeparator());
        }
        pw.flush();
        // 关闭输入流
        socket.shutdownInput();

        // 5.关闭资源
        pw.close();
        os.close();
        br.close();
        isr.close();
        is.close();
        socket.close();
        serverSocket.close();
    }
}

3.客户端编程

客户端使用Socket编程步骤:

  1. 创建Socket对象,指明需要连接的服务器的地址和端口号
  2. 连接建立后,通过输出流想服务器端发送请求信息
  3. 通过输入流获取服务器响应的信息
  4. 关闭响应资源
package edu.java.net.socket.tcp;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.Socket;

/**
 * TCP Socket 套接字客户端
 *
 */
public class ClientSocketDemo {
    public static void main(String[] args) throws Exception {

        // 1.创建客户端Socket,指定服务器地址和端口
        Socket socket = new Socket("localhost", 10086);

        // 2.获取输出流,向服务器端发送信息
        OutputStream os = socket.getOutputStream();
        // 字节输出流
        PrintWriter pw = new PrintWriter(os);
        // 将输出流包装成打印流
        // 注意结尾的换行,提示服务端一行结束
        pw.write("用户名:admin" + System.lineSeparator());
        pw.write("密码:123456" + System.lineSeparator());
        pw.flush();
        socket.shutdownOutput();

        // 3.获取输入流,并读取服务器端的响应信息
        InputStream is = socket.getInputStream();
        BufferedReader br = new BufferedReader(new InputStreamReader(is));
        String info = null;
        while ((info = br.readLine()) != null) {
            System.out.println("客户端收到消息:" + info);
        }
        // 4.关闭资源
        br.close();
        is.close();
        pw.close();
        os.close();
        socket.close();

    }
}

4.服务端多线程编程

实际场景中,一个服务端往往可以支持多个客户端的连接,为多个客户端提供服务。

实现服务器与多客户端之间的通信步骤:

  1. 服务器端创建ServerSocket,循环调用accept()等待客户端连接
  2. 客户端创建一个socket并请求和服务器端连接
  3. 服务器端接受客户端请求,创建socket与该客户建立专线连接
  4. 建立连接的两个socket在一个单独的线程上通信
  5. 服务器端继续等待新的连接
    Java Socket编程之基于TCP协议通信_第2张图片
package edu.java.net.socket.tcp;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * TCP Socket 套接字服务端
 */
public class ServerSocketDemo {
    public static void main(String[] args) throws Exception {
        concurrentServer();
    }

    /**
     * 多线程服务端,能同时接收多个客户端的请求,并且会话结束后关掉对应Socket通道,服务端继续运行
     */
    public static void concurrentServer() {

        int count = 0;
        try {
            @SuppressWarnings("resource")
            ServerSocket serverSocket = new ServerSocket(10086);
            while (true) {
                System.out.println("服务端已经启动,等待客户端的连接...");
                Socket socket = serverSocket.accept();
                count++;
                System.out.println("监听到客户端的连接数量=" + count);
                // 启动一个线程
                ServerThread serverThread = new ServerThread(socket);
                serverThread.start();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

}

// 服务器多线程处理的实际线程类
class ServerThread extends Thread {

    private int serverName = this.hashCode();

    // 和本线程相关的socket
    private Socket socket = null;

    public ServerThread(Socket socket) {
        this.socket = socket;
    }

    @Override
    public void run() {

        try {
            // 1.获取输出流,响应客户端的请求
            OutputStream os = socket.getOutputStream();
            PrintWriter pw = new PrintWriter(os);
            pw.write(serverName + ">欢迎您访问服务端!" + System.lineSeparator());
            pw.flush();

            // 2.获取输入流,并读取客户端信息
            InputStream is = socket.getInputStream();
            BufferedReader br = new BufferedReader(new InputStreamReader(is));
            String info = null;
            while ((info = br.readLine()) != null) {
                System.out.println(serverName + ">服务端接收到消息:" + info);
                pw.write("服务端收到:" + info + System.lineSeparator());
            }

            pw.flush();
            socket.shutdownInput();

            // 3.关闭资源
            pw.close();
            os.close();
            br.close();
            is.close();
            socket.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

    }
}

你可能感兴趣的:(java,tcp/ip,开发语言)