收获:1,加深了对多线程的一边一边的理解,可以将行为写成不同的类然后多线程
2,IO流的复习!
3,多线程中一边读取一边操作时容器最好(CopyOnWriteArrayList);
4,Tcp流程的熟悉;
5,封装!!!代码的复用以及整洁!!!
改进:1,注释
2,对其中更多内容的封装,比如消息等
/**
* 聊天室服务端
* 实现接受和发送消息
* 私聊
* @author 小帆敲代码
*
*/
public class ChatServer {
static CopyOnWriteArrayList<Channel> all=new CopyOnWriteArrayList();
public static void main(String[] args) throws IOException {
ServerSocket server=new ServerSocket(8888);
while(true) {
Socket client=server.accept();
System.out.println("一个客户端已连接");
//添加至系统容器
Channel channel=new Channel(client);
all.add(channel);
new Thread(channel).start();
}
}
static class Channel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private boolean isRunning=true;
private Socket client;
private boolean isName;
private String name;
public Channel(Socket client) {
isName=true;
isRunning=true;
this.client=client;
try {
dis=new DataInputStream(client.getInputStream());
dos=new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
release();
}
}
//接受消息
public String receive() {
String msg="";
try {
msg=dis.readUTF();
} catch (IOException e) {
release();
}
return msg;
}
//发送消息
public void send(String msg) {
if(!msg.equals("")) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
release();
}
}
}
//给别人发送消息
public void sendOthers(String msg) {
//私聊
//获取名字和内容
if(msg.startsWith("@"))
{
int idx=msg.indexOf(":");
String othername=msg.substring(1, idx);
msg=msg.substring(idx+1);
for(Channel others:all) {
if(others.getName().equals(othername))
{
others.send(this.name+"悄悄对你说:"+msg);
break;
}
}
}
else if(!msg.equals("")) {
for(Channel others:all) {
if(others==this)
this.send("我:"+msg);
else
others.send(this.name+":"+msg);
}
}
}
//释放资源
public void release() {
isRunning=false;
Utils.close(dis,dos,client);
}
@Override
public void run() {
String msg;
while(isRunning) {
if(isName)
{
msg=receive();//读
this.name=msg;
isName=false;
}
else
{
msg=receive();//读
sendOthers(msg);//写
}
}
release();//释放资源
}
public String getName() {
return this.name;
}
}
}
* 客户端
*
* @author 小帆敲代码
*
*/
public class ChatClient {
Socket client=new Socket("localhost",8888);
new Thread(new Send(client)).start();
new Thread(new Receive(client)).start();
}
* 接收类
* @author 小帆敲代码
*
*/
public class Receive implements Runnable{
private DataInputStream dis;
private Socket client;
private boolean isRunning;
public Receive(Socket client) {
isRunning=true;
this.client=client;
try {
dis=new DataInputStream(client.getInputStream());
} catch (IOException e) {
System.out.println("==4==");
release();
}
}
private String receive() {
try {
return dis.readUTF();
} catch (IOException e) {
System.out.println("==5==");
release();
}
return "";
}
@Override
public void run() {
while(isRunning) {
String msg=receive();
System.out.println(msg);
}
}
public void release() {
isRunning=false;
Utils.close(dis,client);
}
}
* 发送类
* @author 小帆敲代码
*
*/
public class Send implements Runnable{
private BufferedReader console;
private DataOutputStream dos;
private Socket client;
private boolean isRunning;
private String name;
public Send(Socket client) {
isRunning=true;
this.client=client;
console=new BufferedReader(new InputStreamReader(System.in));
try {
System.out.println("请输入用户名:");
this.name=console.readLine();
System.out.println(name+"欢迎回来");
dos=new DataOutputStream(client.getOutputStream());
this.send(name);
} catch (IOException e) {
System.out.println("==1==");
release();
}
}
/*
* 约定格式:
* 私聊:@xxx:msg
*/
private void send(String msg) {
if(msg!="") {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("==2==");
release();
}
}
}
private String getStrFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
System.out.println("==3==");
release();
}
return "";
}
@Override
public void run() {
while(isRunning) {
String msg=getStrFromConsole();
send(msg);
}
}
private void release() {
isRunning=false;
Utils.close(console,dos,client);
}
}
* 工具类
* @author 小帆敲代码
*
*/
public class Utils {
/**
*释放资源
*/
static void close(Closeable... targets) {
for(Closeable target:targets) {
try {
if(target!=null)
target.close();
}catch(Exception e){
}
}
}
}