客户端
public class SQClient {
private String ip;
private int port;
public SQClient(String ip, int port) {
super();
this.ip = ip;
this.port = port;
}
/**
* 进入聊天室
* @throws UnknownHostException
* @throws IOException
*/
public void startTalking() throws UnknownHostException, IOException{
Socket s = new Socket(ip,port);
//启动消息接收线程
new MsgReceiver(s).start();
//发送消息
Scanner sc = new Scanner(System.in);
String msg = sc.nextLine();
while(true){
Utils.sendMsg(s.getOutputStream(), msg);
if(Objects.equals("/bye", msg)){
break;
}
msg = sc.nextLine();
}
}
public static void main(String[] args) throws UnknownHostException, IOException {
SQClient client = new SQClient("*自己的IP地址", 8090);
client.startTalking();
}
}
服务端
public class SQServer {
/**服务端口*/
public static final int PORT = 8090;
/**存储所有跟其他客户端产生socket对象*/
public ArrayList<Socket> sockets = new ArrayList<>();
public void startServer() throws IOException{
ServerSocket server = new ServerSocket(PORT);
Utils.msg("SOFTEEM山寨QQ已启动,等待客户端连接...");
while(true){
//开始循环监听
Socket s = server.accept();
if(!Utils.exsists(s, sockets)){
//将产生的Socket对象存入集合
sockets.add(s);
Utils.msg(s.getInetAddress().getHostAddress()+"进入聊天室,当前总数:"+sockets.size());
//为每一个客户启动聊天服务线程
new MsgServer(s, sockets).start();
}else{
Utils.sendMsg(s.getOutputStream(), "请不要重复进入聊天室!");
s.close();
}
}
}
public static void main(String[] args) throws IOException {
new SQServer().startServer();
}
}
工具类
public class Utils {
public static void msg(String msg){
System.out.println(msg);
}
/**
* 将一个字节输入流解析为一个字符串信息并返回
* @param is
* @return
* @throws IOException
*/
public static String getMsg(InputStream is) throws IOException{
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String msg = "";
while((msg = br.readLine()) != null){
return msg;
}
return null;
}
/**
* 将指定的文本消息通过输出流对象传输到指定的输出源
* @param outputStream
* @param string
*/
public static void sendMsg(OutputStream outputStream, String msg) {
PrintWriter pw = new PrintWriter(outputStream);
pw.println(msg);
pw.flush();
}
/**
* 判断指定的socket是否在集合中存在
* @param s
* @param list
* @return
*/
public static boolean exsists(Socket s,ArrayList<Socket> list){
//获取当前获取的Socket对象绑定ip地址
String ip2 = s.getInetAddress().getHostAddress();
return list.stream().filter(sk->{
//获取遍历到的其中一个Socket对象绑定的ip
String ip1 = sk.getInetAddress().getHostAddress();
return Objects.equals(ip1, ip2);
}).count() > 0 ;
}
}
接收消息端
public class MsgReceiver extends Thread{
private Socket s;
public MsgReceiver(Socket s) {
super();
this.s = s;
}
@Override
public void run() {
try {
//从socket中读取消息并解析为字符串
String msg = Utils.getMsg(s.getInputStream());
while(true){
Utils.msg(msg);
msg = Utils.getMsg(s.getInputStream());
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
消息服务端
用于接受所有客户端发送的消息,并且制作N份拷贝转发给其他的客户端
public class MsgServer extends Thread{
/**当前线程指定的客户端对象*/
private Socket s;
/**目前系统中的所有客户端socket*/
private ArrayList<Socket> sockets;
public MsgServer(Socket s, ArrayList<Socket> sockets) {
super();
this.s = s;
this.sockets = sockets;
}
@Override
public void run() {
try {
//将socket的输入流解析为文本消息
String msg = Utils.getMsg(s.getInputStream());
Date d = new Date();
DateFormat fmt = DateFormat.getInstance();
fmt = new SimpleDateFormat("[yyyy-MM-dd HH:mm:ss]");
String t = fmt.format(d);
//循环收发消息
while(!Objects.equals(msg, "/bye")){
//Utils.msg(s.getInetAddress().getHostAddress()+":"+msg);
//循环遍历所有的Socket对象
for (Socket sk : sockets) {
Utils.sendMsg(sk.getOutputStream(),s.getInetAddress().getHostAddress()+":"+msg+t);
}
//将socket的输入流解析为文本消息
msg = Utils.getMsg(s.getInputStream());
}
//退出
s.close();
sockets.remove(s);
Utils.msg("客户端"+s.getInetAddress().getHostAddress()+"退出,目前人数:"+sockets.size());
} catch (IOException e) {
//e.printStackTrace();
//将退出的客户移除集合
sockets.remove(s);
Utils.msg("客户端"+s.getInetAddress().getHostAddress()+"退出,目前人数:"+sockets.size());
}
}
}
开启服务端:
开启客户端:
发送消息: