

package Karl.Demo.Test;
import java.io.DataOutputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Scanner;
public class Client {
public static void main(String[] args) throws Exception {
//1.创建Sockrt对象,并同时请求与服务端程序连接
Socket socket=new Socket("127.0.0.1",123456);
//创造一个独立线程ClentReaerThread用来接受服务端随时都有可能发送来的数据
//把socket客户端载入到新线程中,表示新线程是用客户端来接受数据,运行新线程
new ClentReaerThread(socket).start();
//得到字节输出流,用来发送给服务端
OutputStream os=socket.getOutputStream();
//把低级字节输出流包装成数据输出流
DataOutputStream dos=new DataOutputStream(os);
Scanner sc=new Scanner(System.in);
System.out.println("----------客户端开启---------");
while (true) {
System.out.println("请输入:");
String msg = sc.nextLine();
//用户输入exit,就退出客户端
if ("exit".equals(msg)) {
System.out.println("-------退出-------");
dos.close();
socket.close();
break;
}
//开始写数据出去
dos.writeUTF(msg);
dos.flush();
}
}
}
package Karl.Demo.Test;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
public class Server {
//创造集合用来收取客户端上线对象
public static List<Socket> onListSocket=new ArrayList<>();
public static void main(String[] args) throws Exception {
System.out.println("----------服务端启动------------");
//1.创建ServerSocket对象,同时为服务器注册端口
ServerSocket serverSocket=new ServerSocket(8888);
while (true) {
//2.使用serversocket对象,调用accept方法,等待客户端连接请求
Socket socket=serverSocket.accept();
//把上线的Socket对象存入集合中
onListSocket.add(socket);
//获取IP地址
System.out.println(socket.getRemoteSocketAddress()+"---------上线---------");
//3.把这个客户端对应的socket通信管道,交给一个独立的线程负责处理
new ServerRraderThread(socket).start();
}
}
}
package Karl.Demo.Test;
import java.io.*;
import java.net.Socket;
public class ServerRraderThread extends Thread{
//定义一个socket
private Socket socket;
//定义一个有参构造器,把获取来的数据交给本接口的socket
public ServerRraderThread(Socket socket){
this.socket=socket;
}
//重写run方法
@Override
public void run() {
try {
//用本接口socket获取到的数据交给字节输入流is
InputStream is=socket.getInputStream();
//把低级字节输入流is包装成数据输入流dis
DataInputStream dis=new DataInputStream(is);
//把读取数据放入死循环
while (true) {
try {
//用数据输入流方法读取数据交给String定义的msg
String msg=dis.readUTF();
//打印
System.out.println(msg);
//把数据msg传给sendMsgToAll方法,用来实现发送给全部客户端
sendMsgToAll(msg);
} catch (IOException e) {
//获取关闭服务器的IP
System.out.println(socket.getRemoteSocketAddress()+"-------离线-----");
//把下线的Socket对象从集合中删除
Server.onListSocket.remove(socket);
//释放资源
socket.close();
dis.close();
break;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
//创建方法用来发送数据
private void sendMsgToAll(String msg) throws IOException {
//遍历所有在线Socket客户端
for (Socket socket1 : Server.onListSocket) {
//把遍历到的客户端管道赋值给低级字节输出流os
OutputStream os=socket1.getOutputStream();
//把低级字节输出流包装成数据输出流dos
DataOutputStream dos=new DataOutputStream(os);
//用数据输出流dos的方法write给遍历到的客户端管道发送数据
dos.writeUTF(msg);
//IO流方法刷新,防止数据发送不出去
dos.flush();
}
}
}
package Karl.Demo.Test;
import java.io.DataInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.net.Socket;
public class ClentReaerThread extends Thread{
//定义一个socket
private Socket socket;
//定义一个有参构造器,把获取来的数据交给本接口的socket
public ClentReaerThread(Socket socket) {
this.socket = socket;
}
@Override
public void run() {
try {
//用本接口socket获取到的数据交给字节输入流is
InputStream is=socket.getInputStream();
//把低级字节输入流is包装成数据输入流dis
DataInputStream dis=new DataInputStream(is);
//把读取数据放入死循环
while (true) {
try {
//用数据输入流方法读取数据交给String定义的msg
String msg=dis.readUTF();
//打印
System.out.println(msg);
} catch (IOException e) {
//获取关闭服务器的IP
System.out.println(socket.getRemoteSocketAddress()+"-------本机离线-----");
//释放资源
socket.close();
dis.close();
break;
}
}
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}