⽤Java原⽣Socket(BIO)做⼀个聊天室实现单聊和聊(附
完整源码)
⽬录
思路
要实现单聊和聊需要考虑哪些⽅⾯?
1、需要有客户端和服务端,客户端给⽤户提供发送消息、接收消息的途径。服务端⽤于接受客户端的连接,并进⾏消息接收、消息处理和消息转发。
2、需要统⼀消息的格式,我这⾥仅仅是定义⼀个Message对象,通过type字段区分消息的类型。
如果做的精细点,可以考虑⾃⼰设计⼀个基于tcp的通讯协议,具体思路可以看我上⼀篇博客的。
3、单聊:服务器把收到的消息转发给⽬标⽤户。聊:服务器收到消息后,转发给指定⼩组的所有⼈。
源码地址在最下⽅,需要的⾃取。
源码分析
⽬录结构
效果
单聊
聊
消息体Message对象
/
**
* 消息
* @author dayrain
@Data
public class Message implements Serializable {
private static final long serialVersionUID = 7753923870637862141L;
/**
* 发送⼈
*/
private String sendFrom;
/**
* 接收⼈
*/
private String sendTo;
/**
* 消息内容
*/
private String content;
/**
* 消息类型
*/
private Integer type;
/
**
* 发送时间
*/
private String sendTime;
/**
* 创建登录消息
* @param sendFrom 登录⼈
* @return 消息体
*/
public static Message createLoginMessage(String sendFrom) {
Message message = new Message();
message.setSendFrom(sendFrom);
message.setType(Constants.MessageType.LOGIN);
message.NowTime());socket编程聊天室基本流程
return message;
}
/**
* 单聊时创建的消息
* @param userId 发送⼈
* @param sendTo 接收⼈
* @param msg 消息
* @return 消息体
*/
public static Message createPrivateMessage(String userId, String sendTo, String msg) { Message message = new Message();
message.setSendFrom(userId);
message.setSendTo(sendTo);
message.setContent(msg);
message.setType(Constants.MessageType.PRIVATE_MESSAGE);
message.NowTime());
return message;
}
/**
* 创建退出消息
* @param userId 需要退出的⽤户名
* @return 消息体
public static Message createExitMessage(String userId) {
Message message = new Message();
message.setType(Constants.MessageType.EXIT);
message.setSendFrom(userId);
message.NowTime());
return message;
}
/**
* 创建组消息
* @param userId 发送⼈
* @param groupId 组号
* @param content 内容
* @return 消息体
*/
public static Message createGroupMessage(String userId, String groupId, String content) { Message message = new Message();
message.setType(Constants.MessageType.GROUP_MESSAGE);
message.setSendFrom(userId);
message.setSendTo(groupId);
message.setContent(content);
message.NowTime());
return message;
}
}
消息具体的类型⼤概有下⾯的⼏种
public interface Constants {
/**
* 消息类型
*/
interface MessageType{
/**
* 单聊
*/
Integer PRIVATE_MESSAGE = 1;
/**
* 聊
*/
Integer GROUP_MESSAGE = 2;
/**
* 系统消息,系统推送时⽤到
*/
Integer SYSTEM_MESSAGE = 3;
/**
* ⽤户登录
*/
Integer LOGIN = 4;
/**
* ⽤户退出
*/
Integer EXIT = 5;
}
/**
* ⽤户循环输⼊消息时的结束标志
*/
String EXIT_FLAG = "exit";
}
/**
* 组
* @author dayrain
*/
@Data
@AllArgsConstructor
@NoArgsConstructor
public class Group {
/**
* 组号
*/
private String groupId;
/**
* 成员
*/
private List<String> userIds;
}
服务端
⾸先服务端肯定是要常驻内存,随时接受来⾃客户端的连接。
/**
* tcp服务端
* @author dayrain
*/
public class TcpServer {
public TcpServer() throws IOException, ClassNotFoundException {
ServerSocket serverSocket = new ServerSocket(8081);
while (true) {
Socket socket = serverSocket.accept();
TcpServerThread tcpServerThread = new TcpServerThread(socket);
tcpServerThread.start();
}
}
public static void main(String[] args) throws IOException, ClassNotFoundException {
new TcpServer();
}
}
Socket socket = serverSocket.accept(); 系统⽤启动后会阻塞在这⾥,直到有客户端连接上。当有客户端连接时,会把socket注⼊到⼀个线程⾥,并启动了这个线程。下⾯是这个线程的源码:
/**
* 服务线程(有⼀个客户端连接,就有⼀条线程)
* @author dayrain
*/
public class TcpServerThread extends Thread{
private final Socket socket;
private InputStream inputStream;
private OutputStream outputStream;
public TcpServerThread(Socket socket) {
this.socket = socket;
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论