读取数据的线程
package socket;
import java.io.*;
/**
* 读线程
*/
public class ReadFromServerThread extends Thread{
//读取对象
InputStream in;
//自己的名字,为了打印好看
String name;
public ReadFromServerThread(InputStream in,String name){
this.in=in;
this.name=name;
}
@Override
public void run() {
try {
BufferedReader br=new BufferedReader(new InputStreamReader(in,"utf-8"));
//获得读取服务器的内容
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
} catch (IOException e) {
e.printStackTrace();
}
}
}
写入数据线程
package socket;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.UnsupportedEncodingException;
import java.util.Scanner;
/**
* 写线程
*/
public class WriteToServerThread extends Thread{
//写的对象
OutputStream os;
String name;
public WriteToServerThread(OutputStream os,String name){
this.os=os;
this.name=name;
}
@Override
public void run() {
//写入数据:控制台,键盘扫描器
Scanner sc=new Scanner(System.in);
//转换
try {
PrintWriter pw=new PrintWriter(new OutputStreamWriter(os,"utf-8"),true);
//写入第一次的时候,为了配合,先写入自己的昵称
pw.println(name);
//不停地写入聊天
while(true){
String line=sc.next();
pw.println(name+"说:"+line);
}
} catch (UnsupportedEncodingException e) {
e.printStackTrace();
}
}
}
服务器发送给客户端线程
package socket;
import java.io.*;
import java.net.Socket;
import java.util.Map;
/**
* 服务器发送给客户端线程
*/
public class ServerForClientThread implements Runnable{
//需要处理的目标线程是哪个
Socket socket;
//给 所有人发信息,用字节流发
// String,PrintWriter
//
Map<String, PrintWriter> map;
//构造器初始化
public ServerForClientThread(Socket socket, Map<String, PrintWriter> map) {
this.socket = socket;
this.map = map;
}
@Override
public void run() {
try {
//获得输入输出流
InputStream in=socket.getInputStream();
OutputStream os=socket.getOutputStream();
//装饰套娃,方便读写操作
PrintWriter pw=new PrintWriter(new OutputStreamWriter(os,"utf-8"),true);
BufferedReader br=new BufferedReader(new InputStreamReader(in,"utf-8"));
//获得对应的聊天目标:线程ID--->对应的用户名
String name=br.readLine();
System.out.println("欢迎"+name+"来到阳阳海王直播间!");
//同时把这一句话发给万茜和所有人
synchronized (this){
map.put(name,pw);
}
//服务器需要把当前的信息发给所有人:服务器首先要读到客户端发来的信息
String line;
while ((line=br.readLine())!=null){
System.out.println(line);
//群发给其他人:可以不发给自己
sendMsg(line,pw);
}
} catch (IOException e) {
e.printStackTrace();
}
}
/**
*
* @param line 当前客户端发送过来的信息
* @param pw1 当前客户端的输出流对象
* 除了自己全部需要发送
*/
private void sendMsg(String line,PrintWriter pw1) {
//迭代map
for(PrintWriter pw:map.values()){
if(!pw.equals(pw1)){
pw.println(line);
}
}
}
}
创建服务器
package socket;
import java.io.IOException;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
import java.util.Map;
//服务器
public class YangyangServer {
public static void main(String[] args) throws IOException {
ServerSocket server=new ServerSocket(8888);//开启个服务器,TCP协议,端口号
//构建全局的共享变量--->数据库
Map<String, PrintWriter> map=new HashMap<>();
System.out.println("等待客户端连接...");
while (true){
Socket client=server.accept();//此方法是阻塞的,直到有客户端连接进来,返回当前客户端对象
System.out.println("有一个客户端进来了!");
//单独的给当前连接进来的客户端开启一个线程
Thread t=new Thread(new ServerForClientThread(client,map));
//线程启动
t.start();
}
}
}
创建客户端1
package socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
//万茜客户端
public class WanqianClient {
public static void main(String[] args) throws IOException {
Socket client=new Socket("localhost",8888);
//封装的输入和输出流
OutputStream os=client.getOutputStream();
InputStream in=client.getInputStream();
//随意的读写给服务器 读和写单独写出来,分别作为2个线程
new ReadFromServerThread(in,"万茜").start();
new WriteToServerThread(os,"万茜").start();
}
}
创建客户端2
package socket;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
//圆圆客户端
public class YuanyuanClient {
public static void main(String[] args) throws IOException {
Socket client=new Socket("localhost",8888);
//封装的输入和输出流
OutputStream os=client.getOutputStream();
InputStream in=client.getInputStream();
//随意的读写给服务器=----? 读和写单独写出来,分别作为2个线程
new ReadFromServerThread(in,"圆圆").start();
new WriteToServerThread(os,"圆圆").start();
}
}
需要多个客户端直接创建客户端就行,读和写单独提取出来,提高代码的复用性,可读性