使用套接字客户端 - 服务器 - 客户端通信实现聊天

时间:2016-04-12 18:12:42

标签: java sockets chat sendfile

我实现了通过套接字进行通信的全局聊天。客户端写入发送到服务器的消息,而不是服务器将消息发送回所有客户端。每个客户端都由一个名为ClientThread的类表示,因此每个客户端都是一个线程。每次新客户端连接时,我都会创建一个新的ClientThread实例,并将所有这些实例存储在列表中。现在我想实现一个私人聊天,这样每个客户端都可以私下与另一个客户端交谈(或者群聊2,3或者更多)。

现在我的问题是如何做到这一点。我的意思是我在想,无论何时客户想要与另一个客户端开始私人对话,都要将此请求发送到服务器,服务器会将这两个ClientThread实例存储在列表中,并且将是唯一一个接收这些请求的人消息。

第一个问题是如何存储这些对话。什么是最好用的?考虑到在私人会话中可以是一个,两个或更多客户端以及客户端可以进行多个私人会话这一事实,我希望能够轻松识别消息的来源以及将其发回的位置。

我还想说,我只通过ChatMessage类的实例进行通信,这是我定义自己的类,它有一个类型字段和一个消息字段。因此,每当用户向另一个用户发送私人消息时,服务器将接收类型为PRIVATEMESSAGE的消息,使用存储的对话遍历所有列表,并将消息发送到发送该请求的特定对话。

//output and input stream
    output = new ObjectOutputStream(socket.getOutputStream());
    input = new ObjectInputStream(socket.getInputStream());

// send messages
    public void sendMessage(Object msg) {
            try {

                output.writeObject(msg);
            } catch (IOException e) {
                e.printStackTrace();
            }
    }


public class ChatMessage implements Serializable {

    protected static final long serialVersionUID = 1112122200L;

    // The different types of message sent by the Client
    // WHOISIN to receive the list of the users connected
    // MESSAGE an ordinary message
    // LOGOUT to disconnect from the Server
    public static final int WHOISIN = 0;

    public static final int MESSAGE = 1;

    public static final int LOGOUT = 2;

    public static final int LOGIN = 3;

    public static final int PRIVATECONVERSATION = 4;

    public static final int PRIVATEMESSAGE = 5;

    private int type;
    private String message;

    // constructor
    public ChatMessage(int type, String message) {
        this.type = type;
        this.message = message;
    }

    // getters
    public int getType() {
        return type;
    }

    public String getMessage() {
        return message;
    }
}

现在是我的第二个问题:

我有没有办法通过这个ChatMessage类发送文件?我的意思是也许我可以有一个单独的字段,每当我得到类型FILE时,我从该字段读取字节?这可能吗?

2 个答案:

答案 0 :(得分:0)

我还编写了一个简单的聊天程序,我创建了一个用户"将消息列表作为字段的类。每条消息都是"来自","到"等和文本。可以为每个用户

分隔迭代消息列表

答案 1 :(得分:0)

对于您的第一个问题,请查看此处,您可以创建一个类似于此处指定的类似表Database Design for storing Chat Messages between people

要发送文件,您可以将它们转换为字节并按如下方式发送: -

public byte[] read() throws IOException
{
    int length = inputStream.readInt();
    byte[] dataBytes = new byte[length];
    inputStream.readFully(dataBytes, 0, dataBytes.length);
    return dataBytes;
}

public void write(byte[] data, Short packetType) throws IOException
{
    outputStream.writeShort(packetType);
    outputStream.writeInt(data.length);
    outputStream.write(data);
    outputStream.flush();
}

将文件转换为字节: -

Path path= Paths.get("file/path");
byte[] data = Files.readAllBytes(path);

将字节转换回文件: -

byte[] data = read();
Path path = Paths.get("C:\myfile.FileType");
Files.write(path, bytes);

发送文件名及其扩展名,然后发送文件,以便在另一端重新创建文件。