Java网络编程(3)Socket实现一个简单的聊天系统

前言

Java网络编程(2)Socket
前面对Socket有了一定的了解,仅仅完成了发送一次信息就关闭的通信,现在写一个可以多次通话的聊天系统

目录

  1. 思考
  2. 可持续读写
  3. 多线程读写
  4. 相互通信
  5. 总结

思考

在这里插入图片描述

前面发送了信息就关闭了Socket,显然不符合平常的聊天系统,还需要改进一下

可持续读写

服务器:

package com.company.NewThread;


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

public class NewSocketServer {
    public static void main(String[] args) throws IOException {
        //serverSocket等待连接
        ServerSocket serverSocket=new ServerSocket(55555);
        //接受连接,创建socket
        Socket socket=serverSocket.accept();
        System.out.println("IP地址:"+socket.getLocalAddress());
        //输出流
        BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
        String str;
        while ((str=reader.readLine())!=null){
            System.out.println(str);
        }
        reader.close();
        socket.close();
        serverSocket.close();
    }
}

客户端:

package com.company.NewThread;

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

public class NewSocketClient {
    public static void main(String[] args) throws IOException {
        //发送连接请求
        Socket socket=new Socket("127.0.0.1",55555);
        //输入流
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in,"UTF-8"));
        //往socket中写入信息
        BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),("UTF-8")));
        //保持通话
        while (true){
            String str=reader.readLine();
            writer.write(str);
            writer.write("\n");
            //刷新缓存区
            writer.flush();
        }


    }

}

服务器:

在这里插入图片描述
客户端:

在这里插入图片描述

通过一个while循环实现可持续的读写,客户端发送的\n换行,服务器仅读一行就可以多次接收信息

多线程读写

要是多个客户端往服务器发送消息会阻塞

因为Socket通信是阻塞式的,一个客户端发送的信息会等到while循环结束才会接收另一个客户端的信息

新客户端A:

package com.company.NewThread;

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

public class ClientA {
    public static void main(String[] args) throws IOException {
        //发送连接请求
        Socket socket=new Socket("127.0.0.1",55555);
        //输入流
        BufferedReader reader=new BufferedReader(new InputStreamReader(System.in,"UTF-8"));
        //往socket中写入信息
        BufferedWriter writer=new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),("UTF-8")));
        //保持通话
        while (true){
            String str=reader.readLine();
            writer.write(str);
            writer.write("\n");
            //刷新缓存区
            writer.flush();
        }
    }
}

在这里插入图片描述

在NewScoketClient没有断开连接,ClientA都无法连接

在这里插入图片描述
通过多线程解决:

服务器:

package com.company.NewThread;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetAddress;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThreadServer {
    public static void main(String[] args) throws IOException {
        //serverSocket等待连接
        ServerSocket serverSocket=new ServerSocket(55555);
		//创建线程池:限定最多50个线程
        ExecutorService executor= Executors.newFixedThreadPool(50);
        while (true) {
            //接受连接,创建socket
            Socket socket = serverSocket.accept();

            System.out.println("IP地址:" + socket.getLocalAddress());
            //线程
            Runnable runnable=()->{
                try {
                    BufferedReader reader=new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
                    String str=null;
                    while ((str=reader.readLine())!=null){


                        System.out.println(str);
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }

            };

            executor.submit(runnable);

        }


    }
}

客户端不变

记得给客户端改一下输入

在这里插入图片描述

服务器的作用完成了,如果两个客户端想要交流怎么解决?

相互通信

创建一个读写线程就可以

SocketWriter:

package com.company.ThreadSocket;

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

public class SocketWriter extends Thread {
    private Socket socket = null;
    private BufferedWriter writer = null;
    private BufferedReader reader = null;

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

    @Override
    public void run() {
        try {
            while (true) {
                writer = new BufferedWriter(new OutputStreamWriter(socket.getOutputStream(),"UTF-8"));
                reader=new BufferedReader(new InputStreamReader(System.in,"UTF-8"));
                String str=null;
                if ((str=reader.readLine())!=null) {
                    writer.write("Socekt:"+str);
                    writer.write("\n");
                    writer.flush();
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

SocketReader:

package com.company.ThreadSocket;

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

public class SocketReader extends Thread {
    private Socket socket = null;
    private BufferedReader reader = null;

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

    @Override
    public void run() {
        try {
            while (true) {
                reader = new BufferedReader(new InputStreamReader(socket.getInputStream(),"UTF-8"));
                System.out.println(reader.readLine());
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

}

SocketServer:

package com.company.ThreadSocket;

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

public class SocketServer {
    public static void main(String[] args) {
        try {
            //1、创建一个服务端
            ServerSocket serverSocket = new ServerSocket(8888);
            //2、接受客户端的连接
            Socket socket = serverSocket.accept();
            System.out.println(socket);
            //3、服务端启动读取线程和写入线程
            new SocketWriter(socket).start();
            new SocketReader(socket).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}


SocketClient:

package com.company.ThreadSocket;

import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;

public class SocketClient {
    public static void main(String[] args){
        try {
            //1、根据IP和端口号创建一个客户端
            Socket socket=new Socket("127.0.0.1",8888);
            //2、启动读取和写入线程
            new SocketReader(socket).start();
            new SocketWriter(socket).start();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
}

创建了四个类:读进程、写进程、服务器、客户端
服务器、客户端通过调用读写进程完成相互通信
在这里插入图片描述

在这里插入图片描述

总结

  1. 上一章完成了简单的通信,这一章是加强版通信
  2. 持续通信通过一个while循环实现
  3. 多线程通信通过线程池实现
  4. 相互通信通过一个读写进程实现
发布了95 篇原创文章 · 获赞 25 · 访问量 4196

猜你喜欢

转载自blog.csdn.net/key_768/article/details/104557114