0
点赞
收藏
分享

微信扫一扫

JavavEE中网络编程Socket套接字Ⅱ(TCP)

GhostInMatrix 2022-10-19 阅读 39

文章目录

TCP流套接字

ServerSocket API

ServerSocket 是创建TCP服务端Socket的API。
ServerSocket构造方法 :

方法签名方法说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定到指定端口

ServerSocket 方法:

方法签名方法说明
Socket accept()开始监听指定端口(创建时绑定的端口),有客户端连接后,返回一个服务端Socket对象,并基于该Socket建立与客户端的连接,否则阻塞等待(接受客户端的连接)
void close()关闭此套接字

Socket accept() 既会给服务器用,也会给客户端用~

Socket API

Socket 构造方法:

方法签名方法说明
Socket(String host, int port)创建一个客户端流套接字Socket,并与对应IP的主机上,对应端口的进程建立连接

构造方法里面制定了IP和端口,构造方法就是在尝试和指定的服务器建立连接

Socket 方法:

方法签名方法说明
InetAddress getInetAddress()返回套接字所连接的地址(对方的ip地址和端口)
InputStream getInputStream()返回此套接字的输入流
OutputStream getOutputStream()返回此套接字的输出流

通过 socket 可以获取到 两个流对象,分别用来读和写~~
TCP是面向字节流的,所以去读写 TCPsocket 本质上 和 读写文件 是一样的~

🪁TcpEchoSever

代码实现TCP 服务器:

package TCP;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
import java.util.concurrent.Executor;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;


public class TcpEchoSever {
    //代码中会设计多个 socket 对象,使用不同的名字来区分,使用listenSeverSocke来进行监听
    public ServerSocket listenSeverSocket = null;

    public TcpEchoSever(int port) throws IOException {
        listenSeverSocket = new ServerSocket(port);
    }

    public void start() throws IOException {
        System.out.println("服务器启动!");
        ExecutorService service = Executors.newCachedThreadPool();
        while (true) {
            //1. 先调用 appect 来 接受客户端的连接
            Socket clientSocket = listenSeverSocket.accept();
            //2.处理这个连接
            //使用线程池保证可以同时处理多个客户端
            service.submit(new Runnable() {
                @Override
                public void run() {
                    processConnect(clientSocket);
                }
            });
        }



    }

    public void processConnect(Socket clientSocket) throws IOException {
        System.out.println("客户端上线!");
        //接下来处理客户端的请求
        //拿到输入流输出流对象
        try(InputStream inputStream = clientSocket.getInputStream();
            OutputStream outputStream = clientSocket.getOutputStream()) {
            //客户端可能会发多条数据
            while(true) {
                //1.读取请求并解析
                Scanner scanner = new Scanner(inputStream);
                if(!scanner.hasNext()) {
                    //读完了,连接断开
                    System.out.printf("客户端读完了:[%s:%d]",clientSocket.getInetAddress().toString(),clientSocket.getPort());
                    break;
                }
                //读取到请求
                String request = scanner.next();
                //2. 根据请求计算响应
                String response = process(request);
                //3.把响应写回给客户端
                PrintWriter printWriter = new PrintWriter(outputStream);
                printWriter.println(response);
                //刷新缓冲区确保数据确实是通过网卡发送出去了
                printWriter.flush();

                //打印日志
                System.out.printf("[客户端ip地址: %s 客户端端口号: %d],请求: %s , 回应: %s \n", clientSocket.getInetAddress().toString(),
                        clientSocket.getPort(),request,response);
            }

        } catch (IOException e) {
            e.printStackTrace();
        }finally {
            clientSocket.close();
        }
    }
    public String process(String requst) {
        return requst;
    }

    public static void main(String[] args) throws IOException {
        TcpEchoSever tcpEchoSever = new TcpEchoSever(9000);
        tcpEchoSever.start();
    }
}


listenSeverSocketclientSocket 的区别:
在这里插入图片描述
在这里插入图片描述

  • ❓为什么要使用多线程?
  • ❓ 为什么要关闭 socket ? 而前面的 listenSocket 以及 udp 程序中的 socket 为什么就没有 close ?
  • ❓为啥UDP没这个问题,而TCP有这个问题呢?

🪁TcpEchoClient

package TCP;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;

public class TcpEchoClient {
    public Socket socket = null;

    public TcpEchoClient(String severIP,int severPort) throws IOException {
        //和服务器建立连接,需要知道服务器在哪
        socket = new Socket(severIP,severPort);
    }

    public void start() throws FileNotFoundException {
        Scanner scanner = new Scanner(System.in);
        try(OutputStream outputStream = socket.getOutputStream();
            InputStream inputStream = socket.getInputStream()) {
            while (true) {
                //1.从控制台读取数据,构造成一个请求
                System.out.print("->");
                String requestStr = scanner.next();
                //2.将请求发给服务器
                PrintWriter requestPrintWriter = new PrintWriter(outputStream);
                requestPrintWriter.println(requestStr);
                //如果不flush,可能导致请求没有真发出去
                requestPrintWriter.flush();
                //3.从服务器读取Tcp响应数据
                Scanner response = new Scanner(inputStream);
                String responseStr = response.next();
                //4.把响应显示到界面上
                System.out.println(responseStr);
            }

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

    }

    public static void main(String[] args) throws IOException {
        TcpEchoClient tcpEchoClient = new TcpEchoClient("127.0.0.1",9000);
        tcpEchoClient.start();
    }
}

  • ❓为什么Scanner 也不用关闭?

总结

你可以叫我哒哒呀
本篇到此结束
“莫愁千里路,自有到来风。”
我们顶峰相见!
举报

相关推荐

0 条评论