在之前的基础上添加了自定义消息协定:消息头+消息内容
去实现用户的登录注册功能
具体代码如下:
Client类:
public class MClient {
public static void main(String[] args) throws IOException {
new MClient().StartMClient();
}
public OutputStream os;
public InputStream is;
public void StartMClient() throws IOException {
//创建客户端
Socket socket = new Socket("127.0.0.1",9999);
//获取输入输出流
os = socket.getOutputStream();
is = socket.getInputStream();
//线程启动 不实时读取消息
new Thread(new Runnable() {
@Override
public void run() {
while(true){
try {
//读消息头 同样分三种情况
int head = is.read();
switch(head){
case MessageType.LOGIN:
//根据读取的结果进行判断
int b = is.read();
if(b == MessageType.YES){
System.out.println("登录成功");
}else{
System.out.println("登录失败");
}
break;
case MessageType.CHAT:
break;
case MessageType.REGISTER:
break;
}
//读取消息
String msg = readMsg();
System.out.println(msg);//给消息打印出来
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
}).start();
//传入账号密码的数据
String username = "21", password = "20";
os.write(pcm0204.server.MessageType.LOGIN);
sendMsg(username + ":" + password);
//发送消息
while(true){
Scanner scan = new Scanner(System.in);//获得键盘输入
String line = scan.nextLine();
sendMsg(line);
}
}
//读取消息
public String readMsg() throws IOException {
byte[] b = new byte[1024];
is.read(b);
String msg = new String(b);
return msg.trim();//去掉周围空白部分
}
//发送消息
public void sendMsg(String msg) throws IOException {
String str = msg + "\r\n";
os.write(str.getBytes());
os.flush();
}
}
消息头的实现接口
//信息头使用接口 登录 注册 私聊 广播 聊天 yes no
public interface MessageType {
public static final byte LOGIN = 1;
public static final byte REGISTER = 2;
public static final byte PRIVATE = 3;
public static final byte GROUP = 4;
public static final byte CHAT = 5;
public static final byte YES = 6;
public static final byte NO = 7;
}
用户类:
public class User {
public String username;
public String password;
public Integer userID;
public User(){
}
public User(String password, String username) {
this.password = password;
this.username = username;
}
public User(String password, String username, Integer userID) {
this.password = password;
this.username = username;
this.userID = userID;
}
public String getUsername() {
return username;
}
public void setUsername(String username) {
this.username = username;
}
public String getPassword() {
return password;
}
public void setPassword(String password) {
this.password = password;
}
public Integer getUserID() {
return userID;
}
public void setUserID(Integer userID) {
this.userID = userID;
}
}
Server类:
public class MServer {
public static void main(String[] args) throws IOException {
new MServer().StartMServer();
}
public Map<Integer,Socket> map;
public int UserID;
public List<User> userList = new ArrayList<>();
//构筑方法初始化注册账号
public MServer(){
//先注册五个账号
for(int i = 1; i <= 5; i++){
userList.add(new User(i + "1" , i + "1"));
}
}
public void StartMServer() throws IOException {
//创建服务端
ServerSocket server = new ServerSocket(9999);
Map<Integer,Socket> map = new HashMap<>();
int UserID = 1;
//得用while true去实现
while(true) {
//去连接客户端
Socket socket = server.accept();
//把客户端放到map中
map.put(UserID, socket);
//创建线程 启动
ServerThread serverThread = new ServerThread(socket, map, UserID++,userList);
new Thread(serverThread).start();
}
}
}
ServerThread类:
public class ServerThread implements Runnable{
public Socket socket;
public InputStream is;
public OutputStream os;
public int UserID;
public Map<Integer,Socket> map;
public List<User> userList;
public ServerThread(Socket socket,Map<Integer,Socket> map,int UserID,List<User> userList){
this.socket = socket;
this.map = map;
this.UserID = UserID;
this.userList = userList;
try {
os = socket.getOutputStream();
is = socket.getInputStream();
sendMsg(UserID, os,"客户端连接成功");
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//自定义消息协议: 消息头+消息内容
public void run() {
while(true){
try {
//读取消息头
int head = is.read();
String msg = readMsg();
switch(head){
//先分三种情况 登录 注册 私聊
case MessageType.LOGIN:
handleLogin(msg);
break;
case MessageType.REGISTER:
break;
case MessageType.CHAT:
String[] msgArr = msg.split(":");
if(msgArr[0].equals("g")){
//群发 不发送自己
for(Map.Entry<Integer,Socket> entry : map.entrySet()){
Socket s = entry.getValue();
if(s != socket){
OutputStream output = s.getOutputStream();
sendMsg(UserID,output,msg);
}
}
}else{
//指定用户私聊
Integer UserId = Integer.parseInt(msgArr[0]);
//根据id找到私聊对象
Socket s = map.get(UserId);
OutputStream output = s.getOutputStream();
//发送的内容是msgArr[1]
sendMsg(UserID,output,msgArr[1]);
}
System.out.println("Client : " + msg);
break;
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
//处理登录请求的 String msg 存的是 账号和密码两部分 同样用:分割
public void handleLogin(String msg) throws IOException {
//分割消息
String[] msgArr = msg.split(":");
//遍历用户列表
for(User user : userList){
if(user.getUsername().equals(msgArr[0]) && user.getPassword().equals(msgArr[1])){
//返回登录成功的消息
os.write(MessageType.LOGIN);
os.write(MessageType.YES);
return;
}
}
//返回登录失败的消息
os.write(MessageType.LOGIN);
os.write(MessageType.NO);
}
//读取消息
public String readMsg() throws IOException {
byte[] b = new byte[1024];
is.read(b);
String msg = new String(b);
return msg.trim();//去掉周围空白部分
}
//发送消息
public void sendMsg(int UserID, OutputStream os, String msg) throws IOException {//确保os是输出流
String str = UserID + ":" + msg + "\r\n";
os.write(str.getBytes());
os.flush();
}
}
具体的文件打包 如下实现:
