客户端:
package homework.chat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client extends AbstractServerClient{
public static void main(String[] args) throws IOException {
Client client = new Client();
Socket socket = new Socket("localhost", 5000);
System.out.println("请输入昵称:");
Scanner s = new Scanner(System.in);
String name = s.nextLine();
client.send(1,name, socket.getOutputStream());
// 从控制台获取输入,向服务器发送信息
new Thread(()->{
try (OutputStream out = socket.getOutputStream()) {
Scanner scanner = new Scanner(System.in);
while(scanner.hasNextLine()) {
String line = scanner.nextLine();
// 发送消息
// 2 获取用户
// 3 内容 群聊
// 4 内容 对方名字 私聊
// 对命令进行分析
char cmd = line.charAt(0);
switch(cmd) {
case '2':
client.send(2, "", out);
break;
case '3':
String content = line.substring(2);
client.send(3, content, out);
break;
case '4':
// 4 bbb 你好
String c2 = line.substring(2);
client.send(4, c2, out);
break;
default:
}
}
} catch (IOException e) {
e.printStackTrace();
}
}).start();
// 接收服务器返回的响应
new Thread(()->{
try (InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream()
) {
client.receive(socket, in, out);
} catch (IOException e) {
}
}).start();
}
@Override
protected void handle(int cmd, String content, Socket socket, InputStream in, OutputStream out) {
switch (cmd) {
case 5:
System.out.println(content);
break;
case 6:
System.out.println(content);
break;
case 7:
System.out.println(content);
break;
case 8:
System.out.println(content);
break;
}
}
}
服务器:
package homework.chat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
public class Server extends AbstractServerClient {
public static void main(String[] args) {
Server server = new Server();
System.out.println("服务器已经开始运行...");
try {
ServerSocket serverSocket = new ServerSocket(5000);
ExecutorService service = Executors.newFixedThreadPool(10);
while (true) {
Socket socket = serverSocket.accept();
// 提交给线程池的一个线程处理任务
service.submit(() -> {
try (InputStream in = socket.getInputStream();
OutputStream out = socket.getOutputStream()
) {
server.receive(socket, in, out);
} catch (IOException e) {
e.printStackTrace();
}
});
}
} catch (IOException e) {
e.printStackTrace();
}
}
// key 是socket, value 是昵称 线程安全的hashmap Concurrent本意是并发
private Map<Socket, String> map = new ConcurrentHashMap<>();
@Override
protected void handle(int cmd, String content, Socket socket, InputStream in, OutputStream out) throws IOException {
switch (cmd) {
case 1:
map.put(socket, content);
send(5, "欢迎[" + content + "]来到聊天室", out);
break;
case 2:
send(6, map.values().toString(), out);
break;
case 3:
// s是所有的socket 对象, value 是昵称
System.out.println("收到的信息:"+content);
String nick = map.get(socket);// 得到发送者的昵称
String c = nick+"说了:"+content;
map.forEach((s, value)->{
try {
send(7, c, s.getOutputStream());
} catch (IOException e) {
e.printStackTrace();
}
});
break;
case 4:
// bbb 你好
String[] array = content.split(" ");
String n = array[0]; // 对方的名字
String c2 = array[1]; // 内容
boolean found = false;
for (Map.Entry<Socket, String> entry :map.entrySet()) {
// 找到了
if(entry.getValue().equals(n)) {
send(8, map.get(socket)+"对你私聊:"+c2, entry.getKey().getOutputStream());
found = true;
break;
}
}
if(!found) {
send(8, "抱歉,聊天室没这个人", out);
}
break;
}
}
}
父类(为了提高代码的复用性)
package homework.chat;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
public abstract class AbstractServerClient {
// cmd 命令类型, content 消息内容,
public void send(int cmd, String content, OutputStream out) throws IOException {
// 协议: 就是客户端与服务器端约定的一种规则
// 第一个字节 : 命令类型
// 2,3 字节: 内容长度 10
// 剩下的是内容
out.write(cmd); // 第一个字节 : 命令类型
byte[] bytes = content.getBytes("utf-8");
int length = bytes.length; // 300
// 0x 23 45
out.write(0xFF & (length >> 8)); // 发送长度的高位
out.write(0xFF & length); // 发送长度的低位
out.write(bytes); // 发送字节内容
}
public void receive(Socket socket, InputStream in, OutputStream out) throws IOException {
while(true) {
int cmd = in.read();
if(cmd == -1) break;
int hi = in.read();
int lo = in.read();
int length = (hi << 8) + lo;
byte[] bytes = new byte[length];
in.read(bytes);
String content = new String(bytes, "utf-8");
// 处理具体处理代码暂未实现 方法()
handle(cmd, content, socket, in, out);
}
}
// 父类还不知道如何处理 cmd 和 content
protected abstract void handle(int cmd, String content, Socket socket, InputStream in, OutputStream out) throws IOException;
}