日志文章

2019-12-30 aflfte2011

TCP聊天室练习实例

服务器端

package com.aflfte.chat05;

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 在线聊天室服务端
 * 1、实现多个客户群聊
 * 2、实现一对一私聊
 * 3、实现系统消息发布
 * @author jinhao
 *
 */
public class Chat {
private static CopyOnWriteArrayList<Channel> all=new CopyOnWriteArrayList<Chat.Channel>();
public static void main(String[] args) throws Exception {
System.out.println("-----------Server-----------");
//打开服务器端口
ServerSocket server=new ServerSocket(8899);
//进行阻塞式接收

while(true) {
Socket client=server.accept();
System.out.println("一个客户端建立了连接");
Channel c=new Channel(client);
all.add(c);//利用容器管理所有成员
new Thread(c) .start();
}
//server.close();
//释放资源

}
//一个客户代表一个Channel
static class Channel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private Socket client;
private boolean isRuning=false;
private String name;
public Channel(Socket client) {
super();
this.client = client;
try {
dis = new DataInputStream(client.getInputStream());
//返回数据
dos=new DataOutputStream(client.getOutputStream());
isRuning=true;
//获取名称
this.name=receive();
this.send("欢迎你"+this.name);
this.sendOthers("欢迎"+this.name+"进入聊天室",true);
} catch (IOException e) {
System.out.println("channel()!!");
release();
}

}
//接收消息
private String receive() {
String msg="";
try {
msg=dis.readUTF();
} catch (IOException e) {
System.out.println("receive!!");
release();
}
return msg;
}
//转发消息
private void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("send!!");
release();
}

}
//群发消息
//@模式:
private void sendOthers(String msg,boolean b) {
boolean isPrivate=msg.startsWith("@");
if(isPrivate) {
int idx=msg.indexOf(":");
String toname=msg.substring(1,idx);
msg=msg.substring(idx+1);
for(Channel c:all) {
if(c.name.equals(toname)) {
c.send(this.name+"悄悄告诉你:"+msg);
break;
}
}
}else {
for(Channel c:all){
if(c==this) {
continue;
}
if(b) {
c.send("系统消息:"+msg);
}else {
c.send(this.name+":"+msg);
}

}
}
}
//释放资源
private void release() {
this.isRuning=false;
all.remove(this);
sendOthers(this.name+"走出了聊天室", true);
Utils.close(dis,dos,client);
}
@Override
public void run() {
while(isRuning) {
String msg=receive();
if(!msg.equals("")) {
//send(msg);
sendOthers(msg,false);
}
}
}

}
}



客户端:
package com.aflfte.chat05;

import java.io.BufferedReader;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * 在线聊天室客户端
 * 1、实现多个客户可以正常收发多条信息
 * 
 * 
 * @author jinhao
 *
 */
public class Client {
public static void main(String[] args) throws Exception {
System.out.println("----Client----");
System.out.println("请输入用户名:");
BufferedReader br=new BufferedReader(new InputStreamReader(System.in));
String name=br.readLine();
//与服务器建立连接
Socket client=new Socket("127.0.0.1",8899);
//客户端发送消息
new Thread(new Send(client,name)).start();
new Thread(new Receive(client)).start();
}
}

其它组件:

package com.aflfte.chat05;

import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;

/**
 * 接收消息
 * @author jinhao
 *
 */
public class Receive implements Runnable {
private DataInputStream dis;
private Socket client;
private boolean isRuning=false;

public Receive(Socket client) {
super();
this.client = client;
try {
dis=new DataInputStream(client.getInputStream());
isRuning=true;
} catch (IOException e) {
System.out.println("Receive()");
release();
}
}
private void release() {
this.isRuning=false;
Utils.close(dis,client);
}
private String receive() {

String datas="";
try {
datas = dis.readUTF();
return datas;
} catch (IOException e) {
System.out.println("receive()");
release();
}
return "";
}
@Override
public void run() {
while(isRuning){
String msg=receive();
if(!msg.equals("")) {
System.out.println(msg);
}
}

}
}


package com.aflfte.chat05;

import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;

/**
 * 发送消息
 * @author jinhao
 *
 */
public class Send implements Runnable {
private BufferedReader into;
private DataOutputStream dos;
private Socket client;
private boolean isRuning=false;
private String name;
public Send(Socket client,String name) {
this.client=client;
this.name=name;
into=new BufferedReader(new InputStreamReader(System.in));
try {
dos=new DataOutputStream(client.getOutputStream());
isRuning=true;
//发送名称
send(name);
} catch (IOException e) {
System.out.println("Send()");
release();
}
}
private void release() {
this.isRuning=false;
Utils.close(dos,client);
}
public String msg() {
try {
return into.readLine();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
return null;
}
public void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
System.out.println("send()");
release();
}
}
@Override
public void run() {
while(isRuning) {
String msg=msg();
if(!msg.equals("")) {
send(msg);
}
}
}
}

package com.aflfte.chat05;

import java.io.Closeable;

/**
 * 释放资源工具类
 * 
 * @author jinhao
 *
 */
public class Utils {
public static void close(Closeable...targets) {
for(Closeable target:targets) {
try {
if(target!=null) {
target.close();
}
}catch(Exception e){
e.printStackTrace();

}
}
}
}



« 注解创建与反射使用 | TCP实现多用户登录»