TCP网络编程 聊天室(群聊与私聊)完整代码实现
实现工具:Socket、多线程、IO流
实现效果图
Client.java
package com.maple.tcp;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* Client based on tcp protocol
*
* @author RhymeChiang
* @date 2017/10/22
*/
public class Client {
public static void main(String[] args) {
try {
System.out.println(" Please input your name!");
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
String name = br.readLine();
Socket client = new Socket("localhost", 8888);
new Thread(new Send(client, name)).start();
new Thread(new Receive(client)).start();
} catch (IOException e) {
e.printStackTrace();
}
}
}
Server.java
package com.maple.tcp;
import static org.hamcrest.CoreMatchers.instanceOf;
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;
/**
* tcp server
*
* @author RhymeChiang
* @date 2017/10/22
*/
public class Server {
/**
* server
*/
private ServerSocket server = null;
/**
* list of client
*/
private List<AClient> list = null;
public Server() throws IOException {
server = new ServerSocket(8888);
list = new ArrayList<>();
}
public void start() {
while (true) {
AClient client = new AClient();
list.add(client);
new Thread(client).start();
}
}
/**
* each Client has a dependant Thread
*
* @author RhymeChiang
* @date 2017/10/22
*/
private class AClient implements Runnable {
private DataInputStream dis = null;
private DataOutputStream dos = null;
private Socket client = null;
private boolean isRunning = true;
private String clientName = null;
public AClient() {
try {
client = server.accept();
dis = new DataInputStream(client.getInputStream());
dos = new DataOutputStream(client.getOutputStream());
clientName = dis.readUTF();
send(" Welcome!" + clientName);
officialSendOthers(" Hi,everyone!" + clientName + " joined us");
} catch (IOException e) {
isRunning = false;
IOUtil.closeAll(dos, dis);
list.remove(this);
}
}
/**
* receive message from client
*
* @return
* @throws IOException
*/
public String receive() {
try {
return dis.readUTF();
} catch (IOException e) {
isRunning = false;
IOUtil.closeAll(dos, dis);
list.remove(this);
}
return "";
}
public void send(String msg) {
try {
dos.writeUTF(msg);
dos.flush();
} catch (IOException e) {
isRunning = false;
IOUtil.closeAll(dos, dis);
list.remove(this);
}
}
/**
* send message to others
*
* @param msg
*/
public void sendOthers(String msg) {
if(list.size()==0) {
send(" "+"sorry,there is nobody in this chat room now");
return;
}
for (AClient a : list) {
if (a == this) {
continue;
}
a.send(" "+clientName + " said to everyone:" + msg);
}
}
public void officialSendOthers(String msg) {
for (AClient a : list) {
a.send(msg);
}
}
public String getClientName() {
return clientName;
}
/**
* if the msg is a private conversation
*
* @param msg
* @return
*/
public boolean privateSession(String msg) {
String reg = "@[a-zA-Z0-9_-]{3,16}:";
String msgHead = msg.substring(0,msg.indexOf(":")+1);
if (msgHead.matches(reg)) {
// target private conversation
String name = msg.substring(msg.indexOf("@") + 1, msg.indexOf(":"));
// the content of private conversation
String sendMsg = msg.substring(msg.indexOf(":") + 1);
for (AClient a : list) {
if (a.getClientName().equals(name)) {
// send conversation
a.send(" "+this.getClientName() + " said to you: " + sendMsg);
return true;
}
}
send(" "+name + " is not online");
return false;
}
return false;
}
@Override
public void run() {
while (isRunning) {
String msg = receive();
System.out.println(msg);
// private conversation
if (!privateSession(msg)) {
sendOthers(msg);
}
}
}
}
public static void main(String[] args) {
try {
new Server().start();
} catch (IOException e) {
e.printStackTrace();
}
/*
* String msg = "@Rhyme:nihao";
* System.out.println(msg.substring(msg.indexOf("@") + 1, msg.indexOf(":")));
*/
}
}
Send.java
package com.maple.tcp;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* thread of send
*
* @author RhymeChiang
* @date 2017/10/22
*/
public class Send implements Runnable {
/**
* outputStream
*/
private DataOutputStream dos = null;
/**
* console inputStream
*/
private BufferedReader console = null;
/**
* the mark of is thread running well
*/
private boolean isRunning = true;
/**
* the name of current client
*/
private String clientName;
public Send(Socket client,String name) {
super();
try {
this.clientName = name;
dos = new DataOutputStream(client.getOutputStream());
console = new BufferedReader(new InputStreamReader(System.in));
//send clintName to server
dos.writeUTF(clientName);
} catch (IOException e) {
// when it comes to exception close current thread
isRunning = false;
// close input/output streams
IOUtil.closeAll(dos);
}
}
/**
* get message from console
*
* @return the message is going to be send
* @throws IOException
*/
public String getMsgFormConsole() {
try {
return console.readLine();
} catch (IOException e) {
//e.printStackTrace();
IOUtil.closeAll(console);
}
return "";
}
/**
* send message
*
* @param msg
* message going to be send
*/
private void send(String msg) {
try {
//make sure the msg is not null and not ""
if(null!=msg&&!msg.equals("")) {
dos.writeUTF(msg);
dos.flush();
}
} catch (IOException e) {
isRunning = false;
IOUtil.closeAll(dos);
}
}
@Override
public void run() {
while (isRunning) {
//send message from console
send(getMsgFormConsole());
}
}
}
Receive.java
package com.maple.tcp;
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
/**
* Receiver of tcp client
*
* @author RhymeChiang
* @date 2017/10/22
*/
public class Receive implements Runnable {
/**
* input stream from the server
*/
private DataInputStream dis = null;
/**
* input stream from the server
*/
private boolean isRunning = true;
public Receive(Socket client) {
super();
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
isRunning = false;
IOUtil.closeAll(dis);
}
}
/**
* receive message from server
*/
public void receive() {
try {
String str = dis.readUTF();
System.out.println(str);
} catch (IOException e) {
isRunning = false;
IOUtil.closeAll(dis);
}
}
@Override
public void run() {
while (isRunning) {
receive();
}
}
}
IOUtil.java
package com.maple.tcp;
import java.io.Closeable;
import java.io.IOException;
/**
* util of io close
* @author RhymeChiang
* @date 2017/10/22
*/
public class IOUtil {
public static void closeAll(Closeable...io) {
for(Closeable i : io) {
if(null!=i) {
try {
i.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
}