【问题标题】:Implementing a chat using sockets client-server-client communication使用套接字客户端-服务器-客户端通信实现聊天
【发布时间】:2016-08-03 12:32:39
【问题描述】:

我已经实现了一个通过套接字进行通信的全局聊天。客户端写入发送到服务器的消息,然后服务器将消息发送回所有客户端。每个客户端都由一个名为 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 类型时,我都会从该字段中读取字节?这可能吗?

【问题讨论】:

  • 我建议实现房间的概念,即每个房间都是与多个成员对话的一个实例。看看一个叫做 SmartFoxServer 的东西——它是一个可以处理这个问题并使用自定义代码进行 Java 扩展的工具。可能不适合您正在寻找的东西/矫枉过正,但值得评论!

标签: java sockets chat sendfile


【解决方案1】:

对于你的第一个问题,看看这个你可以创建一个类似的表,这里指定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);

发送文件名及其扩展名,然后以您可以在另一端重新创建文件的方式发送文件。

【讨论】:

  • 问题是我只通过 ChatMessage 实例进行通信。有没有办法可以将这些字节存储在 ChatMessage 实例中?
  • @AlexChihaia 您可以创建一个字节数组列表并将文件字节数组保留为数组列表的一个元素,但通常您希望将文件保存在本地硬盘上的某个位置,您可以创建临时文件或将这些文件设置为 deleteOnExit() 以便在程序退出时删除它们
【解决方案2】:

我还编写了一个简单的聊天程序,并创建了一个“用户”类,其中包含消息列表作为字段。每条消息都是一个带有“from”、“to”等和文本的对象。消息列表可以为每个用户迭代分离

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-12-15
    • 2012-08-30
    • 2012-11-02
    • 2016-04-09
    • 2020-10-10
    相关资源
    最近更新 更多