1.单线程模式:
创建服务端:
第一步,准备地址和端口;第二步,创建一个ServerSocket对象;
第三步,等待客户端连接;最后一步,数据接收和发送。
public class SingleThreadServer {
public static void main(String[] args) {
//1. 准备地址和端口
int port = 1314;
try {
//2. ServerSocket
ServerSocket serverSocket = new ServerSocket(port);
//3. 等待客户端连接
Socket client = serverSocket.accept();
//4. 数据接收和发送
//4.1 接收
InputStream in = client.getInputStream();
Scanner scanner = new Scanner(in);
System.out.println("客户端说:"+scanner.nextLine());
//4.2 发送
OutputStream out = client.getOutputStream();
PrintStream printStream = new PrintStream(out);
printStream.println("欢迎,欢迎");
printStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建客户端:
第一步,准备服务端地址和端口号;第二步,创建客户端Socket连接服务器,
最后一步,数据传输(数据的发送和接收)。
public class SingleThreadClient {
public static void main(String[] args) {
//1. 服务端地址,端口号
String ip = "127.0.0.1";//本机IP地址
int port = 1314;
try {
//2.Socket
Socket client = new Socket(ip,port);
//3.数据传输(键盘输入,输出到显示屏)
//3.1 发送数据
OutputStream out = client.getOutputStream();
PrintStream printStream = new PrintStream(out);
printStream.println("服务器,我来了");
printStream.flush();
//3.2 接收数据
InputStream in = client.getInputStream();
Scanner scanner = new Scanner(in);
System.out.println("来自服务端的数据:"+scanner.nextLine());
} catch (IOException e) {
e.printStackTrace();
}
}
}
结果如下:
2.多线程模式:
上面的Server和Client只是进行了简单的通信操作:服务器端接收到客户端连接之后,服务器端向客户端输出一个字符串,而客户端也只是读取服务器端的字符串后就退出了。
实际应用中的客户端则可能需要和服务器端保持长时间通信,即服务器端需要不断地读取客户端数据,并向客户端写入数据;客户端也不需要不断地读取服务器端数据,并向服务器端写入数据。
创建服务端:
首先创建一个与客户端交互的任务处理;
public class ClientHandler implements Runnable {
//储存所有注册的客户端
private static final Map<String, Socket> socketMap = new ConcurrentHashMap<>();
private final Socket client;
private String name;
public ClientHandler(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
//获取客户端输入流
InputStream in = this.client.getInputStream();
Scanner scanner = new Scanner(in);
while (true) {
String line = scanner.nextLine();
if (line.startsWith("register:")) {
String[] segments = line.split(";");
if (segments.length == 2 && segments[0].equals("register")) {
String name = segments[1];
register(name);
}
continue;
}
if (line.startsWith("groupChat:")) {
String[] segments = line.split(":");
if (segments.length == 2 && segments[0].equals("groupChat")) {
String message = segments[1];
groupChat(message);
}
continue;
}
if (line.startsWith("privateChat:")) {
String[] segments = line.split(":");
if (segments.length == 3 && segments[0].equals("privateChat")) {
String name = segments[1];
String message = segments[2];
privateChat(name, message);
}
continue;
}
if (line.equalsIgnoreCase("bye")) {
quitChat();
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
private void quitChat() {
socketMap.remove(this.name);
System.out.println(this.name + "下线了");
printOnlineClient();
}
private void privateChat(String name, String message) {
Socket socket = socketMap.get(name);
if (socket != null) {
sendMessage(socket, this.name + " 说:" + message);
}
}
private void groupChat(String message) {
for(Map.Entry<String,Socket> entry:socketMap.entrySet()) {
Socket socket = entry.getValue();
if (socket == this.client) {
continue;
}
sendMessage(socket, this.name + "说:" + message);
}
}
private void register(String name) {
this.name = name;
socketMap.put(name,this.client);
System.out.println(name + "注册到系统中");
sendMessage(this.client, "欢迎," + name + "注册成功");
printOnlineClient();
}
//打印当前在线客户人数
private void printOnlineClient() {
System.out.println("当前在线的客户端有:" + socketMap.size() + "个,名称列表如下:");
for(String name:socketMap.keySet()) {//keySet()取得所有的key信息
System.out.println(name);
}
}
//发指定消息到客户端
private void sendMessage(Socket client, String s) {
try {
OutputStream out = client.getOutputStream();
PrintStream printStream = new PrintStream(out);
printStream.println(s);
printStream.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
}
创建服务端主程序。
public class MultiThreadServer {
public static void main(String[] args) {
int port = 1314;
final ExecutorService executorService = Executors.newFixedThreadPool(2 * Runtime.getRuntime().availableProcessors());
try {
ServerSocket serverSocket = new ServerSocket(port);
System.out.println("服务端启动,运行在:" + serverSocket.getLocalSocketAddress());
while (true) {
final Socket socket = serverSocket.accept();
System.out.println("客户端连接,来自:" + socket.getRemoteSocketAddress());
executorService.execute(new ClientHandler(socket));
}
} catch (IOException e) {
e.printStackTrace();
} finally {
executorService.shutdown();
}
}
}
创建客户端:
首先创建一个读取服务端信息线程;
public class ReadDataFromServerThread extends Thread{
private Socket client;
public ReadDataFromServerThread(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
InputStream in = client.getInputStream();
Scanner scanner = new Scanner(in);
while (true) {
try {
String message = scanner.nextLine();
System.out.println("来自服务端>" +
message);
}catch (NoSuchElementException e) {
break;
}
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
再创建一个发送信息给服务端的线程;
public class WriteDataToServerThread extends Thread{
private Socket client;
public WriteDataToServerThread(Socket client) {
this.client = client;
}
@Override
public void run() {
try {
OutputStream out = client.getOutputStream();
PrintStream printStream = new PrintStream(out);
Scanner scanner = new Scanner(System.in);
while (true) {
System.out.print("请输入>");
String message = scanner.nextLine();
printStream.println(message);
printStream.flush();
if(message.equals("bye")){
break;
}
}
this.client.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
最后客户端主程序。
public class MultiThreadClient {
public static void main(String[] args) {
String ip = "127.0.0.1";//本机IP地址
int port = 1314;
try {
final Socket socket = new Socket(ip,port);
new WriteDataToServerThread(socket).start();
new ReadDataFromServerThread(socket).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
先启动服务端,再启动多个客户端。
结果如下: