1.Server.java
package com.kennosaur.net.tcp.chat;
import java.awt.List;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.Iterator;
/**
* 创建服务器
* 读取数据: 输入流
*写出数据: 输出流
* @author Administrator
*
*/
public class Server {
private ArrayList<MyChannel> all = new ArrayList<MyChannel>();
public static void main(String[] args) throws IOException {
/*只接收一个客户端
ServerSocket server = new ServerSocket(9999);
Socket client = server.accept();
DataInputStream dis = new DataInputStream(client.getInputStream());
DataOutputStream dos =new DataOutputStream(client.getOutputStream());
while (true) {
//输入流
String msg = dis.readUTF();
System.out.println(msg);
//输出流
dos.writeUTF("服务器-->"+msg);
dos.flush();
}
*/
new Server().start();
}
public void start() throws IOException {
ServerSocket server = new ServerSocket(9999);
while (true) {
Socket client = server.accept();
MyChannel channel = new MyChannel(client);
all.add(channel); //统一管理
new Thread(channel).start(); //一条道路
}
}
/**
* 一个客户端一条道路
* 1.输入流;
* 2.输出流;
* 3.接收数据;
* 4.发送数据;
* @author Administrator
*
*/
private class MyChannel implements Runnable {
private DataInputStream dis;
private DataOutputStream dos;
private boolean isRunning = true;
private String name;
public MyChannel(Socket client) {
try {
dis = new DataInputStream(client.getInputStream());
dos =new DataOutputStream(client.getOutputStream());
this.name = dis.readUTF();
this.send("欢迎进入聊天室"); //发送给自己
sendOthers(this.name+"进入了聊天室",true);
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dis,dos);
}
}
/**
* 读取数据
* @return
*/
private String receive() {
String msg="";
try {
msg= dis.readUTF();
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dis);
all.remove(this); //移除自身
}
return msg;
}
/**
* 发送数据
*/
private void send(String msg) {
if (null==msg||msg.equals("")) {
return;
}
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dos);
all.remove(this); //移除自身
}
}
/**
* 发送给其他客户端
*/
private void sendOthers(String msg, boolean sys) {
//是否为私聊
if (msg.startsWith("@")&&msg.contains(":")) { //私聊
//获取name
String name = msg.substring(1,msg.indexOf(":"));
String content = msg.substring(msg.indexOf(":")+1);
for (MyChannel other : all) {
if (other.name.equals(name)) {
other.send(this.name+"对您悄悄地说:"+content);
}
}
}else {
//遍历容器
for (MyChannel other : all) {
if (other==this) {
continue;
}
if (sys) { //系统信息
other.send("系统信息:"+msg);
}else {
//发送给其他客户端
other.send(this.name+"对所有人说:"+msg);
}
}
}
}
@Override
public void run() {
while(isRunning) {
//send(receive()); //发送给连接的客户端
sendOthers(receive(),false); //发送给其他客户端
}
}
}
}
2.Client.java
package com.kennosaur.net.tcp.chat;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 创建客户端: 发送数据+接收数据
* 写出数据: 输出流
* 读取数据: 输入流
*
* 输入流与输出流在同一个线程内, 应该独立出来 ,彼此独立
* @author Administrator
*
*/
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
// Socket client = new Socket("localhost", 9999);
//控制台输入流
// BufferedReader console = new BufferedReader(new InputStreamReader(System.in));
// DataOutputStream dos =new DataOutputStream(client.getOutputStream());
// DataInputStream dis = new DataInputStream(client.getInputStream());
// while (true) {
// String info = console.readLine();
// //输出流
// dos.writeUTF(info);
// dos.flush();
//输入流
// String msg = dis.readUTF();
// System.out.println(msg);
// }
System.out.println("请输入名称:");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String name = br.readLine();
if (name.equals("")) {
return;
}
Socket client = new Socket("localhost", 9999);
new Thread(new Send(client,name)).start(); //一条发送路径
new Thread(new Receive(client)).start(); //一条接收路径
}
}
3.客户端Send.java
package com.kennosaur.net.tcp.chat;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* 发送数据 线程
* @author Administrator
*
*/
public class Send implements Runnable{
//控制台输入流
private BufferedReader console ;
//管道输出流
private DataOutputStream dos;
//控制线程标识
private boolean isRunning = true;
//名称
private String name;
public Send() {
console = new BufferedReader(new InputStreamReader(System.in));
}
public Send(Socket client,String name) {
this();
try {
dos = new DataOutputStream(client.getOutputStream());
this.name = name;
send(this.name);
} catch (IOException e) {
// TODO Auto-generated catch block
isRunning = false;
CloseUtil.closeAll(dos,console);
}
}
//1.从控制台接收数据
private String getMsgFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
}
return "";
}
/**
*1.从控制台接收数据
*2.发送数据
*/
public void send(String msg) {
if(null!=msg&&!msg.equals("")) {
try {
dos.writeUTF(msg);
dos.flush(); //强制刷新
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dos,console);
}
}
}
@Override
public void run() {
//线程体
while(isRunning) {
send(getMsgFromConsole());
}
}
}
4.客户端Receive.java
package com.kennosaur.net.tcp.chat;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
/**
* 接收线程
* @author Administrator
*
*/
public class Receive implements Runnable{
//输入流
private DataInputStream dis;
//线程标识
private boolean isRunning = true;
public Receive() {
}
public Receive(Socket client) {
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
// TODO Auto-generated catch block
isRunning = false;
CloseUtil.closeAll(dis);
}
}
/**
* 接收数据
* @return
*/
public String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
isRunning = false;
CloseUtil.closeAll(dis);
}
return msg;
}
@Override
public void run() {
//线程体
while (isRunning) {
System.out.println(receive());
}
}
}
6.关闭所有流工具类CloseUtil.java
package com.kennosaur.net.tcp.chat;
import java.io.Closeable;
import java.io.IOException;
/**
* 关闭流的方法
* @author Administrator
*
*/
public class CloseUtil {
public static void closeAll(Closeable... io) {
for (Closeable temp:io) {
if(null!=temp) {
try {
temp.close();
} catch (IOException e) {
}
}
}
}
}