这节我们实现群聊和私发的功能(本节内容较少,重要的是要有制定消息协议的想法,代码包在绑定资源里)
一、思路
由于多了区分消息类型的需求,所以需要更新消息协议
这里我确定消息协议为
消息类型 好友名称长度 好友名称 (信息类型) 消息长度 消息内容
并规定私聊输入格式 为**++@+用户名+空格+信息,群聊默认++**
然后只需要更改客户端的发送函数send 、服务端的接收函数receive 和消息处理函数proClintMsg(Socket socket)
下面我们来实现它
二、代码实现
首先更改客户端的发送函数send,判断其是群聊还是私聊,私聊1 群聊2,如果是群聊就使用原代码(前面加上发送消息类型)
如果是私聊就单独写其处理逻辑
第一步先拆分传入的信息,前半段为用户名,后半段为信息,然后依次转成字节数据传出(注意先传消息类型,这个是需要自行添加的,原消息中没有)
java
public void send(String message){
//文字消息: 消息类型 好友名称长度 好友名称 信息类型 消息长度 消息内容
//先通过@来区分是否是私聊
char c1=message.charAt(0);
try {
OutputStream os=socket.getOutputStream();
if(c1=='@'){
//私聊
int index=message.indexOf(" ");//找到空格的下标
String friendName=message.substring(1,index);
String msg=message.substring(index+1);
System.out.println("正在发送给:"+friendName);
//组装消息内容
// message="1"+friendName.length()+friendName+msg.length()+msg;
os.write(1);
int fn=friendName.getBytes().length;
os.write(fn);
os.write(friendName.getBytes());
int msglen=msg.getBytes().length;
os.write(msglen);
os.write(msg.getBytes());
}else{
os.write(2);//群聊
byte[] msgs=message.getBytes();
int len=msgs.length;
os.write(len);
os.write(msgs);
}
os.flush();
} catch (Exception e) {
throw new RuntimeException(e);
}
}
其次,修改服务端中的接收receive函数
由于传入的消息协议不同,所以需要制定不同的读取方案
如下
java
public String receive(InputStream is){
try {
//读取消息类型 群聊2 私聊2=1
int type=is.read();
if (type==1){
//私聊
int idlen=is.read();
byte[] id=new byte[idlen];
is.read(id);
String friendName=new String(id);
int msglen=is.read();
byte[] msgs=new byte[msglen];
is.read(msgs);
String msg=new String(msgs);
return "1"+"#"+friendName+"#"+msg;
}else{
//群聊
int len=is.read();
byte[] msgs=new byte[len];
is.read(msgs);
String msg=new String(msgs);
System.out.println("收到:"+msg);
return "2"+"#"+" "+"#"+msg;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
同理,在消息处理函数中,虽然消息协议相同,但是传出对象不同,所以同样需要分类判断,具体发方法如下(代码意思很明显,就不过多赘述了)
java
public void proClintMsg(Socket socket){
//注意:循环速度太快,导致cpu被占满,io流根本没机会运行,所以这里加一个println,让cpu空闲下来
new Thread(()->{
//登录
//读取用户名
String UserName=proLogein(socket);
ClientUser cu=new ClientUser(UserName,socket);
//保存ClientUser对象
SocketList.add(cu);
while(true) {
try {
InputStream is=cu.socket.getInputStream();
System.out.println("监听"+cu.socket.getPort()+"消息中:");//顺序不对?
String msg=receive(is);
//区分群聊消息还是私发消息
String [] datas=msg.split("#");
String type=datas[0];
String friendName=datas[1];
String msgs=datas[2];
if(type.equals("1")){
for(int i=0;i<SocketList.size();i++){
ClientUser cu1=SocketList.get(i);
if(cu1.account.equals(friendName)){
msgs=cu.account+"说:"+msgs;
send(msgs,cu1.socket.getOutputStream());
break;
}
}
}else{
replyMsg(cu,msgs);
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}).start();
}
其他没有变化
这样,群聊和私发的功能便初步实现了