今日,写完了基本的内容,就是已经写好了客户端和服务端。并且通过hashmap模拟数据库,能够实现多个用户登录。先看客户端第1个:
2个客户端
在看看服务端的图片:
看看服务端的主要代码:
首先就是创建一个serversocket的对象。然后在通过hashmap模拟数据库。
那个check方法,就是用来判断客户端传输过来的用户user,密码是否正确,正确返回true。
在public QQServer()这个构造方法中,通过while循环,不断监听客户端,接收客户端传输过来的user对象。通过check方法判断,若用户密码正确,则返回给客户端一个成功的反馈,然后服务端创建一个线程(这里室单独写的一个类Thread),与客户端保持联系,并将这个线程放入集合中管理。若用户密码错误,返回客户端失败的反馈,关闭通讯,并输出错误信息。
package com.ww.qqserve.service;
import com.ww.qqcommon.MassageType;
import com.ww.qqcommon.Message;
import com.ww.qqcommon.User;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
public class QQServer {
private ServerSocket ss=null;
//用hashmap存储用户。
private static HashMap<String,User> validUsers = new HashMap<>();
static {
validUsers.put("100",new User("100","123456"));
validUsers.put("lybyyds",new User("lybyyds","1314520.."));
validUsers.put("王祖贤",new User("王祖贤","123456"));
validUsers.put("柳岩",new User("柳岩","123456"));
}
public static boolean check(String userId,String paw){
User user =validUsers.get(userId);
if(user==null){
return false;
}
if(!user.getPassWd().equals(paw)){
return false;
}
return true;
}
public QQServer(){
try {
System.out.println("服务器在9999端口监听。。。");
ss=new ServerSocket(9999);
while (true){//监听是不断的
Socket socket = ss.accept();
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
User u = (User) ois.readObject();
ObjectOutputStream oos = new ObjectOutputStream(socket.getOutputStream());
Message message=new Message();
//先验证特殊的,因为这里需要使用到数据库
if(check(u.getUserId(),u.getPassWd())){//登录成功
message.setMesType(MassageType.MESSAGE_LOGIN_SUCCEED);
oos.writeObject(message);
//创建一个线程,与客户端保持联系。
ServerConnectClientThread serverConnectClientThread = new ServerConnectClientThread(socket, u.getUserId());
serverConnectClientThread.start();
//把线程对象 放入集合中
ManageClientThreads.addClientThread(u.getUserId(),serverConnectClientThread);
}else{//登录失败
System.out.println("用户"+ u.getUserId() +"登录失败 ");
message.setMesType(MassageType.MESSAGE_LOGIN_FAIL);
oos.writeObject(message);
socket.close();
}
}
} catch (Exception e) {
e.printStackTrace();
}finally {
try {
ss.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
服务端的线程代码如下;
package com.ww.qqserve.service;
import com.ww.qqcommon.Message;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.Socket;
public class ServerConnectClientThread extends Thread {
private Socket socket;
private String userId;//链接到服务器的id
public ServerConnectClientThread(Socket socket, String userId) {
this.socket = socket;
this.userId = userId;
}
@Override
public void run() {
while(true){
try {
System.out.println("服务端与客户端"+ userId+"保持通讯,读取数据");
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Message me = (Message) ois.readObject();
//后面会使用messa
} catch (Exception e) {
e.printStackTrace();
}
}
}
}
在看看客户端的主要代码:
这段代码,是连接服务端的代码,主要是给服务端传输一个user对象,看其是否存在于服务端中,
若存在于服务端,收到了成功的反馈,就创建了一个与服务端联系的线程类(单独写的一个类)。
并将其放入集合中管理。若失败则关闭通讯。
package com.ww.qqservice;
import com.ww.qqcommon.MassageType;
import com.ww.qqcommon.Message;
import com.ww.qqcommon.User;
import com.ww.qqservice.ClientConnectServerThread;
import com.ww.qqservice.ManageClientConnectServerThread;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.net.InetAddress;
import java.net.Socket;
public class qqcheck {
private User u =new User();
private Socket socket;
public boolean checkUser(String userId,String pwd) {
boolean b =false;
u.setUserId(userId);
u.setPassWd(pwd);
try {
socket = new Socket(InetAddress.getByName("192.168.2.9"),9999);
ObjectOutputStream oos = null;
oos = new ObjectOutputStream(socket.getOutputStream());
oos.writeObject(u);
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
Message ms = null;
ms = (Message) ois.readObject();
if(ms.getMesType().equals(MassageType.MESSAGE_LOGIN_SUCCEED)){
//创建一个ClientConnectServerThread
ClientConnectServerThread clientConnectServerThread = new ClientConnectServerThread(socket);
clientConnectServerThread.start();
ManageClientConnectServerThread.addClientConnectServerThread(userId,clientConnectServerThread);
b=true;
}else {
socket.close();
}
} catch (Exception e) {
e.printStackTrace();
}
return b;
}
}
客户端中的线程,代码:
package com.ww.qqservice;
import com.ww.qqcommon.Message;
import java.io.IOException;
import java.io.ObjectInputStream;
import java.net.Socket;
public class ClientConnectServerThread extends Thread {
private Socket socket;
public ClientConnectServerThread(Socket socket){
this.socket=socket;
}
@Override
public void run() {
//因为线程在后台与服务器通讯,所以需要用while循环
while(true){
System.out.println("客户端等待从服务器端发送的消息");
try {
ObjectInputStream ois = new ObjectInputStream(socket.getInputStream());
//如果没有发送,线程就会阻塞在这里
Message mes=(Message) ois.readObject();
} catch (IOException | ClassNotFoundException e) {
e.printStackTrace();
}
}
}
public Socket getSocket(){
return socket;
}
}