1.实现用户注册上线,下线
2.实现群聊和私聊功能
3.实现统计当前在线人数
1.首先,要实现服务端与客户端之间的连接
这里是使用套接字建立TCP连接:
(1)服务器端先实例化一个描述服务器端口号的ServerSocket对象
(2)客户端要创建Socket对象来连接指定的服务器端
(3)服务器端调用ServerSocket类的accept()方法来监听连接到服务器端的客户端信息
(4)若服务器端与客户端连接成功,双方将返回一个Socket对象,此时双方可以进行通信
(5)服务器端与客户端使用I/O流进行连接,服务端的输出流连接客户端的输入流,客户端的输出流连接服务端的输入流
(6)使用close()方法关闭套接字(一定要记得关闭)
2.因为是拥有一个服务端来实现多个客户端的连接,此处还要解决的是多线程的问题。
每个客户端需要两个线程,来分别处理向服务端发送消息和向服务端接收消息
而服务端,当每增加一个客户端与服务端连接,服务端都要多创建一个线程来处理与客户端的连接
单线程实现:
客户端
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
/**
* @author LXY
* @email [email protected]
* @date 2018/7/20 15:46
*/
//客户端
public class SingleClient {
public static void main(String[] args) throws IOException {
//客户端连接服务器,返回套接字Socket对象
Socket socket = new Socket("127.0.0.1",6666);
//获取服务端的输出流,向服务器端输出内容
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("我是客户端" + socket.getLocalPort());
//获取服务器端的输入流,读取服务器端的内容
Scanner scanner = new Scanner(socket.getInputStream());
scanner.useDelimiter("\n");
if(scanner.hasNext())
{
System.out.println(scanner.next());
}
//关闭流
socket.close();
}
}
服务端
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Scanner;
/**
* @author LXY
* @email [email protected]
* @date 2018/7/20 15:34
*/
//服务端
public class SingleServer {
public static void main(String[] args) throws IOException {
//创建服务器端的ServerSocket对象,等待客户端进行连接
ServerSocket serverSocket = new ServerSocket(6666);
System.out.println("服务器的端口号为6666,等待客户端连接。。。");
//侦听并接收服务器端的连接,返回套接字Socket对象
Socket socket = serverSocket.accept();
//获取客户端的输入流,读取客户端的输入内容
Scanner scanner = new Scanner(socket.getInputStream());
scanner.useDelimiter("\n");
if(scanner.hasNext())
{
System.out.println("客户端发来消息:" + scanner.next());
}
//获取客户端的输出流,向客户端输出内容
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("客户端你好,我是服务器端:" + serverSocket.getLocalPort());
//关闭流
serverSocket.close();
}
}
多线程实现
客户端
import java.io.IOException;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
/**
* @author LXY
* @email [email protected]
* @date 2018/7/20 15:55
*/
//客户端
//客户端读取服务器端信息的线程
class ClientReadServer implements Runnable
{
private Socket socket;
public ClientReadServer(Socket socket)
{
this.socket = socket;
}
public void run() {
try {
Scanner scanner = new Scanner(socket.getInputStream());
while (scanner.hasNext())
{
System.out.println(scanner.next());
}
socket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
//客户端向服务端发送信息的线程
class ClientSendServer implements Runnable
{
private Socket socket;
public ClientSendServer(Socket socket)
{
this.socket = socket;
}
public void run() {
try {
PrintStream printStream = new PrintStream(socket.getOutputStream());
Scanner scanner = new Scanner(System.in);
while (true)
{
String msg = null;
if(scanner.hasNext())
{
msg = scanner.next();
printStream.println(msg);
}
if(msg.equals("bye"))
{
scanner.close();
printStream.close();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
public class MultiClient {
public static void main(String[] args) throws IOException {
Socket socket = new Socket("127.0.0.1",6666);
Thread read = new Thread(new ClientReadServer(socket));
Thread send = new Thread(new ClientSendServer(socket));
read.start();
send.start();
}
}
服务端
import java.io.IOException;
import java.io.PrintStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.Map;
import java.util.Scanner;
import java.util.Set;
import java.util.concurrent.ConcurrentHashMap;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
/**
* @author LXY
* @email [email protected]
* @date 2018/7/20 16:12
*/
class Server implements Runnable
{
private static Map map = new ConcurrentHashMap();
private Socket socket;
public Server(Socket socket)
{
this.socket = socket;
}
public void run() {
try {
Scanner scanner = new Scanner(socket.getInputStream());
String msg = null;
while (true)
{
if(scanner.hasNextLine())
{
msg = scanner.nextLine();
Pattern pattern = Pattern.compile("\r");
Matcher matcher = pattern.matcher(msg);
msg = matcher.replaceAll("");
//用户注册——格式:userName:用户名
if(msg.startsWith("userName:"))
{
String userName = msg.split("\\:")[1];
userRegist(userName,socket);
continue;
}
//群聊——格式:G:群聊信息
else if(msg.startsWith("G:"))
{
firstStep(socket);
String str = msg.split("\\:")[1];
groupChat(socket,str);
continue;
}
else if(msg.startsWith("P:") && msg.contains("-"))
{
firstStep(socket);
String userName = msg.split("\\:")[1].split("-")[0];
String str = msg.split("\\:")[1].split("-")[1];
privateChat(socket,userName,str);
continue;
}
else if(msg.contains("bye"))
{
firstStep(socket);
userExit(socket);
continue;
}
else
{
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("格式输入错误");
continue;
}
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void firstStep(Socket socket) throws IOException {
Set> set = map.entrySet();
for(Map.Entry entry:set)
{
if(entry.getValue().equals(socket))
{
if(entry.getValue() == null)
{
PrintStream printStream = new PrintStream(socket.getOutputStream());
printStream.println("请先进行注册操作!格式为:[userName:用户名]");
}
}
}
}
private void userRegist(String userName, Socket socket) {
map.put(userName,socket);
System.out.println("用户名:" + userName + "客户端" + socket +"上线了!!");
System.out.println("当前在线人数为" + map.size() + "人");
}
private void groupChat(Socket socket, String msg) throws IOException {
Set> set = map.entrySet();
String userName = null;
for(Map.Entry entry:set)
{
if(entry.getValue().equals(socket))
{
userName = entry.getKey();
break;
}
}
for(Map.Entry entry:set)
{
Socket client = entry.getValue();
PrintStream printStream = new PrintStream(client.getOutputStream());
printStream.println(userName + "说" + msg);
}
}
private void privateChat(Socket socket, String userName, String msg) throws IOException {
String curUser = null;
Set> set = map.entrySet();
for(Map.Entry entry:set)
{
if(entry.getValue().equals(socket))
{
curUser = entry.getKey();
break;
}
}
Socket client = map.get(userName);
PrintStream printStream = new PrintStream(client.getOutputStream());
printStream.println(curUser + "私聊说" + msg);
}
private void userExit(Socket socket) {
String userName = null;
for(String key:map.keySet())
{
if(map.get(key).equals(socket))
{
userName = key;
break;
}
}
map.remove(userName,socket);
System.out.println("用户" + userName + "已下线");
}
}
public class MultiServer {
public static void main(String[] args) {
try {
ServerSocket serverSocket = new ServerSocket(6666);
//使用线程池
ExecutorService executorService = Executors.newFixedThreadPool(20);
for(int i = 0;i < 20;i++)
{
System.out.println("欢迎来到聊天室。。。");
Socket socket = serverSocket.accept();
System.out.println("新人加入。。。");
executorService.execute(new Server(socket));
}
executorService.shutdown();
serverSocket.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}