服务端代码
package com.cyj.tcp.chat2;
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 Chyjrily
*
*/
public class Server {
private List<Channel> all = new ArrayList<Channel>(); //通过容器,管理管理其他的管道,转发时只需遍历容器
public static void main(String[] args) throws IOException {
new Server().start(); //调用下面的方法,调用静态方法
}
public void start() throws IOException {
ServerSocket server = new ServerSocket(2500);
while(true) {
Socket client = server.accept();
Channel ch = new Channel(client); //建立一条通道
all.add(ch); //将自己加入容器
new Thread(ch).start(); //启动分配管道的多线程
}
}
//每个客户端分配一条道路
class Channel implements Runnable{
private DataInputStream dis;
private DataOutputStream dos;
private boolean isRunning = true;
public Channel(Socket client) throws IOException{
try {
dis = new DataInputStream(client.getInputStream());
dos =new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
dis.close();
dos.close();
isRunning = false;
}
}
//读取数据
private String receive() {
String msg = "";
try {
msg = dis.readUTF();
} catch (IOException e) {
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) {
all.remove(this);//管道出现异常,移除出容器
}
}
//转发内容给其他的客户端
private void sendOthers() {
String msg = receive();
//遍历容器
for(Channel other:all) {
if(other == this) {
continue;
}
//转发
other.send(msg);
}
}
public void run() {
while(isRunning) {
sendOthers();
}
}
}
}
客户端代码
package com.cyj.tcp.chat2;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
/**
* 客户端可以发送和接收数据,且相互独立
* 数据的接收和发送不能够有先后顺序
* @author Chyjrily
*
*/
public class Client {
public static void main(String[] args) throws UnknownHostException, IOException {
Socket client = new Socket("DESKTOP-BEUJ3C4",2500);
new Thread(new Send(client)).start(); //调用发送数据的多线程
new Thread(new Receive(client)).start(); //调用接收数据的多线程
}
}
接收数据创建的多线程
package com.cyj.tcp.chat2;
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.net.Socket;
/**
* 接收线程
* @author Chyjrily
*
*/
public class Receive implements Runnable {
private boolean isRunning = true;
//管道输入流
private DataInputStream dis;
public Receive() {
}
public Receive(Socket client) throws IOException {
try {
dis = new DataInputStream(client.getInputStream());
} catch (IOException e) {
isRunning = false;
dis.close();
}
}
public String receive() throws IOException {
while(true) {
String msg = "没有接收到数据";
dis.readUTF();
return msg;
}
}
public void run(){
while(isRunning) {
try {
System.out.println(receive());
} catch (IOException e) {
e.printStackTrace();
System.out.println("接收失败");
}
}
}
}
发送数据创建的多线程
package com.cyj.tcp.chat2;
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
/**
* 通过多线程,将客户端的数据的发送与数据的接收想一致
* @author Chyjrily
*
*/
public class Send implements Runnable {
//控制台输入流
private BufferedReader console;
//管道输出流
private DataOutputStream dos;
//管道是否能正常运行的标识
private boolean isRunning = true;
public Send(){
console = new BufferedReader(new InputStreamReader(System.in));
}
public Send(Socket client) throws IOException{ //通过接收数据,将管道传过来
this();
try {
dos = new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
isRunning = false; //管道是一切传输的基础,如果不运行,直接终止程序
dos.close();
console.close();
}
}
//从控制台接收数据
private String getMsg() throws IOException{
return console.readLine();
}
public void send() throws IOException {
String msg = getMsg();
if(null != msg) {
dos.writeUTF(msg);
dos.flush();
}
}
public void run() {
while(isRunning) { //是否运行的标志
try {
send();
} catch (IOException e) {
e.printStackTrace();
System.out.println("服务器多线程启动失败");
}
}
}
}