客戶端:
package com.chen.Web.tcp.chat01;
import java.io.BufferedReader;
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 {
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
System.out.println("請輸入這個客戶端的名字");
String name = br.readLine();
// 創建客戶端,連接本機的9999端口
Socket client = new Socket("localhost", 9999);
new Thread(new Send_Thread(client, name)).start();
new Thread(new Receive_Thread(client)).start();
}
}
服務器端:
package com.chen.Web.tcp.chat01;
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.List;
/**
* 服務器端
* @author Administrator
*
*/
public class Server {
List<MyChannel> continer = new ArrayList<MyChannel>();
public static void main(String[] args) throws IOException {
new Server().start();
}
/**
* 由於內部類的原因,創建一個啓動方法
* @throws IOException
*/
public void start() throws IOException {
// 創建服務端 ServerSocket 加服務器端口
ServerSocket server = new ServerSocket(9999);
// 阻塞式監聽接口
while(true) {
Socket client = server.accept();
MyChannel channel = new MyChannel(client);
continer.add(channel);
new Thread(channel).start();
}
}
/**
* 一個客戶端,一條通道
* @author Administrator
*
*/
private class MyChannel implements Runnable {
// 輸出流
private DataInputStream is;
// 輸入流
private DataOutputStream os;
// 標識線程是否運轉
private boolean isRunning = true;
private String name;
public MyChannel(Socket client) {
try {
is = new DataInputStream(client.getInputStream());
os = new DataOutputStream(client.getOutputStream());
this.name = is.readUTF();
send("歡迎您進入聊天室");
sendOthers(this.name+"進入聊天室", true);
System.out.println(this.name+"進入聊天室");
} catch (IOException e) {
this.isRunning = false;
IoUtils.closeAll(os, is);
e.printStackTrace();
}
}
/**
* 接收數據
* @return
*/
public String receive() {
try {
return is.readUTF();
} catch (IOException e) {
this.isRunning = false;
IoUtils.closeAll(is);
e.printStackTrace();
}
return null;
}
/**
* 發送數據
* @param msg
*/
public void send(String msg) {
try {
if(msg != null && msg != "")
os.writeUTF(msg);
} catch (IOException e) {
this.isRunning = false;
IoUtils.closeAll(os);
e.printStackTrace();
}
}
/**
* 向其他客戶端發送數據
* 1、私聊:以@開頭+客戶端名+msg. example:@c:你好
* 2、羣聊
* @param msg
* @param isSysInform
*/
public void sendOthers(String msg, boolean isSysInform) {
if(msg.startsWith("@")) {
String name = msg.substring(1, msg.indexOf(":"));
String context = msg.substring(msg.indexOf(":") + 1);
for(MyChannel channel: continer) {
if(channel.name.equals(name)) {
channel.send(this.name+"悄悄對你說:"+context);
}
}
}else {
for(MyChannel channel: continer) {
if(channel == this) {
continue;
}
if(isSysInform) {
channel.send("系統消息:"+msg);
}else {
channel.send(this.name+"對大家說:"+msg);
}
}
}
}
@Override
public void run() {
while(isRunning) {
sendOthers(receive(), false);
}
}
}
}
發送線程:
package com.chen.Web.tcp.chat01;
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_Thread implements Runnable{
// 標準輸入流
private BufferedReader console;
// 輸入流
private DataOutputStream os;
// 標識
private boolean isRunning = true;
private String name;
public Send_Thread() {
console = new BufferedReader(new InputStreamReader(System.in));
}
public Send_Thread(Socket client, String name) {
this();
try {
os = new DataOutputStream(client.getOutputStream());
this.name = name;
send(this.name);
} catch (IOException e) {
this.isRunning = false;
IoUtils.closeAll(os, console);
e.printStackTrace();
}
}
/**
* 發送數據
* @param msg
*/
public void send(String msg) {
try {
if(msg != null && msg != "") {
os.writeUTF(msg);
}
} catch (IOException e) {
this.isRunning = false;
IoUtils.closeAll(os);
e.printStackTrace();
}
}
/**
* 把標準控制檯的輸入轉換成字符串
* @return String
*/
public String msgFromConsole() {
try {
return console.readLine();
} catch (IOException e) {
this.isRunning = false;
IoUtils.closeAll(console);
e.printStackTrace();
}
return null;
}
@Override
public void run() {
while(isRunning) {
send(msgFromConsole());
}
}
}
接收線程:
package com.chen.Web.tcp.chat01;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
/**
* 接收線程:接收來自於socket中的字符串
* @author Administrator
*
*/
public class Receive_Thread implements Runnable{
// 輸出流
private DataInputStream is;
// 標識
private boolean isRunning = true;
public Receive_Thread() {
}
public Receive_Thread(Socket client) {
try {
is = new DataInputStream(client.getInputStream());
} catch (IOException e) {
this.isRunning = false;
IoUtils.closeAll(is);
e.printStackTrace();
}
}
/**
* 接收字符串
* @return
*/
public String receive() {
try {
return is.readUTF();
} catch (IOException e) {
this.isRunning = false;
IoUtils.closeAll(is);
e.printStackTrace();
}
return null;
}
@Override
public void run() {
while(isRunning) {
System.out.println(receive());
}
}
}
工具類:
package com.chen.Web.tcp.chat01;
import java.io.Closeable;
import java.io.IOException;
/**
* 關閉流的工具類
* @author Administrator
*
*/
public class IoUtils {
public static void closeAll(Closeable ... io) {
for(Closeable temp: io) {
if(temp != null) {
try {
temp.close();
} catch (IOException e) {
System.out.println("關閉流出現異常");
e.printStackTrace();
}
}
}
}
}