Socket学习

socket通过三次握手建立连接,通信完成时拆除连接
四要素是:客户端地址,客户端端口,服务端地址,服务端端口
客户端和服务端的代码编写
关于 Thread 类(https://blog.csdn.net/qq_58266033/article/details/123638588)
在java标准库中,提供了一个Thread类,用来表示/操作线程,Thread类可以视为是Java标准库提供的API,Java是支持多线程编程的,在Java中创建好的Thread实例,其实和操作系统中的线程是一一对应的关系,操作系统提供了一组关于线程的API(C语言),Java对于这组API进一步封装之后就变成了Thread类

最简单的创建线程方式 写一个类继承线程Thread类 再重写run方法

服务端Server.java

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws IOException {
        // 新建一个服务器socket  只需要设置端口即可  不需要设置ip
        ServerSocket server = new ServerSocket(2000);

        System.out.println("服务器准备就绪--");
        System.out.println("服务器信息:"+server.getInetAddress()+" P:"+server.getLocalPort());

        // 无限循环 接收来自客户端的请求
        for (;;){
            // 接受客户端  获得客户端的client信息
            Socket client = server.accept();
            // 握手接收到以后 开一个线程执行线程里面的操作
            ClientHandler clientHandler = new ClientHandler(client);
            // 线程执行
            clientHandler.start();
        }
    }

    // 新建一个类 继承线程里面的方法 
    private  static  class  ClientHandler extends  Thread{

        private Socket socket;
        private  boolean flag = true;

        ClientHandler(Socket socket){
            this.socket = socket;
        }
        
        //重写线程里面的run方法
        @Override
        public void run() {
            
            // 先继承原有run方法
            super.run();
            // 打印出客户端的相关信息 
            System.out.println("新客户端连接:"+socket.getInetAddress()+" P:"+socket.getPort());

            try {
                //得到打印流 用于数据输出;服务器
               //客户端的输出流 作为一个打印流 
                PrintStream socketOutput = new PrintStream(socket.getOutputStream());

                //客户端的输入流 转换为BufferedReader 
                BufferedReader socketInput = new BufferedReader(new InputStreamReader(socket.getInputStream()));

                do{
                    //客户端拿到一条数据
                    //从打印流拿到数据
                    String str = socketInput.readLine();
                    if("bye".equalsIgnoreCase(str)){
                        flag=false;

                        socketOutput.println("bye");
                    }else {
                        System.out.println(str);
                        //输出流往客户端写东西   
                        socketOutput.println("回送"+str.length());
                    }
                }
                while (flag);

            }catch (Exception e){
                System.out.println("连接异常断开");
            }finally {
                try {
                    socket.close();
                }catch (IOException e){
                    e.printStackTrace();
                }
            }
            System.out.println("客户端已退出:"+socket.getInetAddress()+" P:"+socket.getPort());
        }
    }
}

客户端Client.java

import java.io.*;
import java.net.Inet4Address;
import java.net.InetSocketAddress;
import java.net.Socket;

// 新建一个客户端 
public class Client {

    // main函数
    public static void main(String[] args) throws IOException {
        
        // 新建一个socket
        Socket socket = new Socket();
        // 设置超时时间
        socket.setSoTimeout(3000);

        // 设置连接本地 端口2000;超时时间3000
        socket.connect(new InetSocketAddress(Inet4Address.getLocalHost(),2000),3000);

        System.out.println("已发起服务器连接,并进入后续流程--");
        System.out.println("客户端信息:"+socket.getLocalAddress()+" P:"+socket.getLocalPort());
        System.out.println("服务器信息:"+socket.getInetAddress()+" P:"+socket.getPort());
      
        //连接到服务器以后 做todo()方法的相关操作 传入socket参数是为了得到服务器的输入流和输出流
        try {
            todo(socket);
        }catch (Exception e){
            System.out.println("异常关闭");
        }

         // 释放资源
        socket.close();
        System.out.println("客户端已退出");
    }

    public static void todo(Socket client) throws  IOException {
        
        // BufferedReader 从字符输入流中读取文本,缓冲各个字符,从而实现字符、数组和行的高效读取。
        // 构建键盘输入流
        //将InputStreamReader转为BufferedReader 
        InputStream inputStream= System.in;
        BufferedReader bufferedReader =  new BufferedReader(new InputStreamReader(inputStream));

        // 得到Client输出流,并转换为打印流
        // outputStream 直接转换为PrintStream  打印流 
        OutputStream outputStream = client.getOutputStream();
        PrintStream socketPrintStream = new PrintStream(outputStream);

        // 得到Client输入流,并转换为BufferedRead 
        InputStream inputStream1 = client.getInputStream();
        BufferedReader bufferedReader1 = new BufferedReader(new InputStreamReader(inputStream1));
        boolean flag = true;
        do {
            //键盘读取一行
            String str = bufferedReader.readLine();
            // 通过打印流发送到服务器
            socketPrintStream.println(str);
            //从服务器读取一行
            String echo = bufferedReader1.readLine();
            // 如果是bye则不做操作 否则打印出来
            if ("bye".equalsIgnoreCase(echo)) {

            }else{
                System.out.println(echo);
            }
        }
        // 重复输入 直到断开
        while(flag);
        //关闭socketPrintStream 释放内存
        socketPrintStream.close();
    }
}

你可能感兴趣的:(Socket学习)