【JAVA】基于socket的无GUI聊天室

其实Socket这个问题困扰我好久了,一直没有好好梳理过,今天花了一天的时间,看了很多资料,写了一个基于Socket的无GUI聊天室,算是对Socket的一个总结吧。

 

关于Socket和SocketServer,这里就不多解释了。直接看图。


 

说明几点:

  • accept是阻塞式的,它会一直等待Client的连接,直到有Client连接时,accept之后的代码才会被执行。
  • 输入输出流的选择可以有很多方式,建议选择DataInputStream和DataOutputStream,因为DataInputStream在读取内容时,直接一个readUTF就可以了,可以省去很多不必要的麻烦。

思路:

  • 服务端:
    • 考虑到接入的客户端不只一个,因此服务端需要一个List来装接入的Socket连接。一个连接代表一个Client。
    • 启动两个线程。一个线程用于接收接入的Client,另一个线程用于接收Client发来的消息,并将消息发送给所有Client(本质即迭代List)。
  • 客户端:
    • 客户端也需要启动两个线程。一个线程用于接收Server发来的消息(实际上是别的Client发给Server,Server转发过来的)。另一个线程用于像Server发送消息。
  • 其它:
    • 需要注意关闭socket时抛异常的情况(因为一个线程还在不停的等待读取信息)。
    • 至于两个线程怎么开,自由度很大,可以自己决定。

Server端代码:

 

package com.ryan.chatRoom;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class Server1 {

    private List<Socket> socketList;
    private Socket socket;
    private ServerSocket server;
    private ExecutorService service;
    private DataOutputStream dos;

    public Server1() throws IOException {

        server = new ServerSocket(10000);
        socketList = new ArrayList<>();
        service = Executors.newCachedThreadPool();

        System.out.println("waiting for client...");
        while (true){
            socket = server.accept();
            socketList.add(socket);
            System.out.println("Client comes...total:" + socketList.size());
            dos = new DataOutputStream(socket.getOutputStream());
            dos.writeUTF("message from server: connect successfully");
            //dos.close();
            service.execute(new ServerThread(socket));

        }
    }

    private class ServerThread implements Runnable{
        Socket socket;
        DataOutputStream dos;
        DataInputStream dis;
        String textFromClient;

        public ServerThread(Socket socket) throws IOException {
            this.socket = socket;
            dis = new DataInputStream(socket.getInputStream());
        }


        @Override
        public void run() {
            try {
                while ((textFromClient=dis.readUTF())!=null){
                    if(textFromClient.equals("exit")){
                        //socket.close();
                        socketList.remove(socket);
                        //dis.close();
                        //dos.close();
                        System.out.println("client leaves...current client:" + socketList.size());
                    }else {
                        for (Socket socket : socketList) {
                            dos = new DataOutputStream(socket.getOutputStream());
                            dos.writeUTF(textFromClient);
                        }
                    }
                }
            } catch (IOException e) {

            }
        }
    }

    public static void main(String[] args) throws IOException {
        new Server1();
    }
}

Client端代码:

package com.ryan.chatRoom;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
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 Client1 {

    private Socket socket;
    private Scanner scanner;
    private DataInputStream dis;
    private DataOutputStream dos;
    private String textFromServer;
    private ExecutorService services;

    public Client1() {
        try {
            socket = new Socket("127.0.0.1", 10000);
            dis = new DataInputStream(socket.getInputStream());
            System.out.println(dis.readUTF());
            services = Executors.newCachedThreadPool();
            services.execute(new ClientThread(socket));

            while ((textFromServer = dis.readUTF()) != null) {
                System.out.println("message from Server:" + textFromServer);
            }
        } catch (IOException e) {
            System.out.println("see you");
            System.exit(0);
        }

    }

    private class ClientThread implements Runnable {

        Scanner scanner;
        DataOutputStream dos;
        Socket socket;
        String sendToServer;

        public ClientThread(Socket socket) throws IOException {
            this.socket = socket;
            dos = new DataOutputStream(socket.getOutputStream());
            scanner = new Scanner(System.in);
        }

        @Override
        public void run() {
            while (true) {
                try {
                    sendToServer = scanner.nextLine();
                    dos.writeUTF(sendToServer);
                    if(sendToServer.equals("exit")){
                        socket.close();
                        dos.close();
                        dis.close();
                        services.shutdown();
                    }
                } catch (IOException e) {
                    System.out.println("see you!");
                    System.exit(0);
                }
            }
        }
    }

    public static void main(String[] args) throws IOException {
        new Client1();
    }
}

注意事项:

  • 先启动Server端,再启动Client端。
  • Server端只能启动一个,Client端可以启动多个。

 

-----------------------------------------------------

请尊重作者劳动成果,

转载请注明出处

http://blog.csdn.net/wait_notify/article/details/69372571
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值