TCP套接字的使用

        Java中使⽤TCP协议通信,使用ServerSocket来建立链接,使用Socket进行通信.

        ServerSocket

        ServerSocket是创建TCP服务端Socket的api,主要方法:

方法签名说明
ServerSocket(int port)创建一个服务端流套接字Socket,并绑定指定端口
Socket accpet()开始监听指定端口,有客户端链接后,返回一个服务端Socket对象,基于这个对象与客户端Socket对象通信,如果没有客户端链接,则阻塞等待,
void close()关闭套接字

        Socket

        socket是客户端socket或服务端接收到客户端建立链接的请求后,返回的服务端socket.不管是客户端Socket还是服务端Socket,都是双方建立链接后,保存对端信息并用来通信的.Socket的主要方法:

方法签名说明
Socket(String host,int port)创建⼀个客⼾端流套接字Socket,并与对应IP的主机上,对应端⼝的进程建⽴连接.
InetAddress getInetAddress()返回套接字所链接的地址
InputStream getInputStream()返回套接字的输入流
OutputStream getOutputStream()返回套接字的输出流

        输入流InputStream与输出流OutputStream分别使用Scanner与PrintWrite进行封装,方便请求与响应的传输.

        建立一个简单的回显服务器

        Server

        服务端负责接收客户端发送来的数据,然后处理相应逻辑,返回给客户端一个响应.

public class TCPEchoServer {
    ServerSocket serverSocket = null;

    public TCPEchoServer(int port) throws IOException {
        serverSocket = new ServerSocket(port);
    }
    
    public void start() throws IOException {
        System.out.println("服务器已启动!");
        //使用线程池来管理线程
        ExecutorService pool = Executors.newCachedThreadPool();
        //接受客户端链接
        while (true){
            Socket clientSocket = serverSocket.accept();
            pool.submit(new Runnable() {
                @Override
                public void run() {
                    try {
                        processConnection(clientSocket);
                    } catch (IOException e) {
                        throw new RuntimeException(e);
                    }
                }
            });
        }
    }

    private void processConnection(Socket clientSocket) throws IOException {
        System.out.printf("[%s:%d]已上线!\n",clientSocket.getInetAddress(),clientSocket.getPort());
        //获取socket中的输入流和输出流
        try(InputStream inputStream = clientSocket.getInputStream();
            OutputStream outputStream = clientSocket.getOutputStream()){
            //扫描客户端请求
            while (true) {
                //用Scanner包装inputStream输入流 方便获取请求
                Scanner scanner = new Scanner(inputStream);
                if(!scanner.hasNext()){
                    //用户不再输入时 跳出循环 当用户断开后也为不再输入
                    System.out.printf("[%s:%d]已下线!\n",clientSocket.getInetAddress(),clientSocket.getPort());
                    break;
                }
                String request = scanner.next();
                //计算响应
                String response = process(request);
                //直接使用outputStream的write方法无法返回换行符"\n",导致客户端处理较为困难
                //选择使用PrintWriter包装outputStream,使用PrintWriter的println方法
                PrintWriter writer = new PrintWriter(outputStream);
                writer.println(response);
                //PrintWriter中存在缓冲区,需要"攒够一波"数据之后才会真正的发送数据
                //使用flush方法,冲刷缓冲器,让缓冲区的内容直接发送出去
                writer.flush();

                //打印服务器日志
                System.out.printf("[%s:%d] req: %s,resp : %s\n",clientSocket.getInetAddress(),
                        clientSocket.getPort(),request,response);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }finally {
            //执行完毕这一次的链接后 关闭链接
            clientSocket.close();
        }
    }

    private String process(String request) {
        return "响应:"+request;
    }

    public static void main(String[] args) throws IOException {
        TCPEchoServer server = new TCPEchoServer(8848);
        server.start();
    }
}

        Client

        客户端负责向服务端发送请求,并等待接收服务端的响应.

public class TCPEchoClient {
    private Socket socket = null;

    public TCPEchoClient(String ip,int port) throws IOException {
        //new操作完成后 开始建立链接 等待服务端accept
        socket = new Socket(ip, port);
    }

    public void start(){
        System.out.println("客户端已启动");
        //接收用户输入的请求
        Scanner input = new Scanner(System.in);
        try(InputStream inputStream = socket.getInputStream();
            OutputStream outputStream = socket.getOutputStream();){
            //不断扫描
            while(true){
                System.out.print("->");
                if(!input.hasNext()){
                    break;
                }
                //获取请求
                String request = input.next();
                PrintWriter writer = new PrintWriter(outputStream);
                writer.println(request);
                writer.flush();
                //接收服务端响应
                Scanner netWork = new Scanner(inputStream);
                String response = netWork.next();
                //向用户展示响应
                System.out.println(response);
            }
        } catch (IOException e) {
            throw new RuntimeException(e);
        }
    }

    public static void main(String[] args) throws IOException {
        TCPEchoClient client = new TCPEchoClient("127.0.0.1",8848);
        client.start();
    }
}

     运行结果:

启动客户端与服务端,从客户端发送请求,查看客户端与服务端的表现.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值