首先在IDE的src文件夹下创建两个类:

客户端向服务端发送数据,需要客户端创建套接字并传入IP地址和端口号,然后创建输出流读取用户输入数据,发送给服务端。服务端需要创建服务端的套接字并传入端口号,然后用套接字去接收,最后使用输入流进行读取。

客户端:

import java.io.IOException;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.util.Scanner;

public class Client {
    public static void main(String[] args){
        try(Socket socket = new Socket("localhost",8080)){
            Scanner scanner = new Scanner(System.in);
            System.out.println("已连接到服务器");
            OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write(scanner.nextLine()+'\n');
            writer.flush();
        } catch (IOException e) {
            System.out.println("服务端连接失败");
            e.printStackTrace();
        }
    }
}

服务端:

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

public class Server {
    public static void main(String[] args){
        try(ServerSocket server = new ServerSocket(8080)) {
            System.out.println("正在等待客户端连接。。。");
            Socket socket = server.accept();
            System.out.println("客户端已链接,IP地址是"+socket.getInetAddress().getHostAddress());
            System.out.println("读取客户端发送的数据:");
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println(reader.readLine());
            socket.close();
        }catch (IOException e){
            e.printStackTrace();
        }

    }
}

然后运行,先运行服务端,然后运行客户端:

如果现在服务器要发送数据确认给客户端,需要写输出流且客户端使用输入流读取:

服务器端:

public class Server {
    public static void main(String[] args){
        try(ServerSocket server = new ServerSocket(8080)) {
            System.out.println("正在等待客户端连接。。。");
            Socket socket = server.accept();
            System.out.println("客户端已链接,IP地址是"+socket.getInetAddress().getHostAddress());
            System.out.println("读取客户端发送的数据:");
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println(reader.readLine());


            OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write("收到\n");
            writer.flush();

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

    }
}

客户端:

public class Client {
    public static void main(String[] args){
        try(Socket socket = new Socket("localhost",8080)){
            Scanner scanner = new Scanner(System.in);
            System.out.println("已连接到服务器");
            OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write(scanner.nextLine()+'\n');
            writer.flush();
            System.out.println("数据已经发送,等待服务端确认");
            BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
            System.out.println("收到服务器响应"+reader.readLine());
        } catch (IOException e) {
            System.out.println("服务端连接失败");
            e.printStackTrace();
        }
    }
}

手动关闭单向的流,比如客户端给服务器发送完消息之后就不使用输出流就可以关闭,不需要等到socket关闭之后才关闭:

Scanner scanner = new Scanner(System.in);
System.out.println("已连接到服务器");
OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
writer.write(scanner.nextLine()+'\n');
writer.flush();
socket.shutdownOutput();
System.out.println("数据已经发送,等待服务端确认");
BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream()));
System.out.println("收到服务器响应"+reader.readLine());
socket.shutdownOutput();

如果不希望服务端等待太长的时间,可以通过调用setSOTimeout:

System.out.println("正在等待客户端连接。。。");
Socket socket = server.accept();
socket.setSoTimeout(3000);  //设定为3秒

此外,如果双方发生意外而通知不到对方,导致对方还持有连接就会占用资源,可以使用setKeepAlive:

socket.setKeepAlive(true);

文件传输使用socket

使用socket进行文件的客户端/服务器端的传输,在客户端需要读取相应的文件输入流,然后将文件内容写到字节输出流,发送给服务端。在服务器端需要使用字节输入流去读取socket的内容,然后写入文件输出流。

客户端:

public class Client {
    public static void main(String[] args){
        try(Socket socket = new Socket("localhost",8080)){
            FileInputStream fileInputStream = new FileInputStream("lhw.txt");
            OutputStream stream = socket.getOutputStream();
            byte[] bytes = new byte[1024];

            int i;
            while((i = fileInputStream.read(bytes))!=-1){
                stream.write(bytes,0,i);
            }
            stream.flush();
            fileInputStream.close();
        } catch (IOException e) {
            System.out.println("服务端连接失败");
            e.printStackTrace();
        }
    }

服务器端:

public class Server {
    public static void main(String[] args){
        try(ServerSocket server = new ServerSocket(8080)) {
            Socket socket = server.accept();
            InputStream stream = socket.getInputStream();
            FileOutputStream fileOutputStream = new FileOutputStream("hxl.txt");
            byte[] bytes = new byte[1024];
            int i;
            while((i =stream.read(bytes))!=-1){
                fileOutputStream.write(bytes,0,i);
            }
            fileOutputStream.flush();
            fileOutputStream.close();
        }catch (IOException e){
            e.printStackTrace();
        }

    }
}

使用浏览器打开socket服务器

当我们打开一个浏览器并点击F12的时候,就会有哟个开发者视图,那我们会发现这个浏览器对应页面中出现的内容实际上都是由一些代码元素构成。这些代码就是前端的html,javascript以及css组成,浏览器实际上是读取服务端的数据进行页面的可视化。

在server的代码里:

public class Server {
    public static void main(String[] args){
        try(ServerSocket server = new ServerSocket(8080)) {
            System.out.println("等待客户端连接...");
            Socket socket = server.accept();
            System.out.println("客户端已经连接,IP地址是:"+socket.getInetAddress().getHostAddress());
            InputStream in = socket.getInputStream();
            System.out.println("接收到客户端数据:");
            while (true){
                int i = in.read();
                if(i == -1) break;
                System.out.print((char)i);
            }
        }catch (IOException e){
            e.printStackTrace();
        }

    }
}

点击余小宁server代码,然后打开Google浏览器,输入http://localhost:8080就发现一直转圈进不去,然后在控制台就得到了:

这是HTTP协议规定的请求头内容,说明浏览器想要访问这个server服务器。那么server就需要按照HTTP协议的规则返回一个规范的响应文本。

下面server开始响应浏览器:

public class Server {
    public static void main(String[] args){
        try(ServerSocket server = new ServerSocket(8080)) {
            System.out.println("等待客户端连接...");
            Socket socket = server.accept();
            System.out.println("客户端已经连接,IP地址是:"+socket.getInetAddress().getHostAddress());
            OutputStreamWriter writer = new OutputStreamWriter(socket.getOutputStream());
            writer.write("HTTP/1.1 200 OK\r\n");
            writer.write("\r\n");
            writer.write("lhw");
            writer.flush();
            socket.close();
        }catch (IOException e){
            e.printStackTrace();
        }

    }
}

运行server文件并再次访问http://localhost:8080/后:

点击f12进入开发者模式,运行server后刷新网页查看Network:

点击localhost,发现状态码是200,是因为我们设置的是writer.write("HTTP/1.1 200 OK\r\n");

根据writer.write("lhw");进行响应的内容会显示在浏览器页面上:

Logo

openEuler 是由开放原子开源基金会孵化的全场景开源操作系统项目,面向数字基础设施四大核心场景(服务器、云计算、边缘计算、嵌入式),全面支持 ARM、x86、RISC-V、loongArch、PowerPC、SW-64 等多样性计算架构

更多推荐