要实现:多个客户端,要使用多线程


(每来一个管道就交给线程,每一个线程都会有自己专属的管道)

package com.itheima.d6_socket2;
import java.io.OutputStream;
import java.io.PrintStream;
import java.net.Socket;
import java.util.Scanner;
/**
* 实现服务端可以同时处理多个客户端的消息
*/
public class ClientDemo1 {
public static void main(String[] args) {
try {
// 1. 创建Socket通信管道请求有服务端的连接
// public Socket(String host, int port) 调用其有参构造器,
// host是服务端的ip地址,port是服务端的地址(要和服务端接通管道)
Socket socket = new Socket("127.0.0.1",7777); // 这里用本机当作服务端
// 2. 从socket通信管道中得到一个字节输出流(写数据,用最高的打印流),负责发送数据
OutputStream os = socket.getOutputStream(); // os是一个输出流对象
// 3. 把低级的字节流包装成打印流
PrintStream ps = new PrintStream(os); // 包装成打印流,打回给os,os是socket(连接的管道的对象)衔接的管道 输出流 // 然后
// 通过socket发送给服务端
Scanner sc = new Scanner(System.in);
while (true) { // 实现多发多收,服务端和客户端都要定义while
System.out.println("请说:");
String msg = sc.nextLine();
// 4. 发送消息
ps.println(msg); // 写数据 要刷新
ps.flush();
}
// 关闭资源(不建议直接关闭资源,TCP可以一直建立连接, 可以让用户离线自动关闭)
// socket.close();
} catch ( Exception e) {
e.printStackTrace();
}
}
}
package com.itheima.d6_socket2;
import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
/**
* 目标:开发Socket网络编程入门代码的服务端,实现接收消息
*/
public class ServiceDemo2 {
public static void main(String[] args) {
try {
System.out.println("服务端启动成功:");
// 1.注册端口 (注意端口号要和客户端写的端口号要一致,这样客户端才能找到服务端)
ServerSocket serverSocket = new ServerSocket(7777);
// a. 定义一个死循环由主线程负责不断的接收客户端的Socket管道连接
while (true){
// 2. 每接收到一个客户端的Socket管道,交给一个独立的子线程负责读取消息
Socket socket = serverSocket.accept();
// getRemoteSocketAddress 得到远程地址(这个是客户端地址)
System.out.println(socket.getRemoteSocketAddress() + "上线了");
// 3. 开始创建独立线程处理socket (每来一个管道就交给线程,每一个线程都会有自己专属的管道)
new ServerReaderThread(socket).start(); // 创建线程对象,并启动
}
} catch ( Exception e) {
e.printStackTrace();
}
}
}
package com.itheima.d6_socket2;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.Socket;
public class ServerReaderThread extends Thread{
private Socket socket; // 创建Socket管道对象
public ServerReaderThread(Socket socket){
this.socket = socket;
}
@Override
public void run() { // 子线程都在这里跑
try {
// 3. 从socket通信管道中得到一个字节输入流
InputStream is = socket.getInputStream(); // 读数据用输入流
// 4. 把字节输入流包装成缓冲字符输入流进行消息的接收
BufferedReader br = new BufferedReader(new InputStreamReader(is));
// 5. 按照行读取消息
String msg;
while ((msg = br.readLine()) != null){ // 如果每收到数据,就会出异常,到catch
System.out.println(socket.getRemoteSocketAddress() + "说了: " + msg);
}
} catch ( Exception e) { // 异常了,就执行这里,表示下线了
System.out.println(socket.getRemoteSocketAddress() + "下线了");
}
}
}