本文是TCP网络编程的练习代码,实现了在eclipse控制台上的群聊和私聊功能。
首先创建服务器端:
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;
public class Server {
public static void main(String[] args) throws IOException {
//创建服务器接口
System.out.println("启动服务端");
ServerSocket server=new ServerSocket(9999);
//储存客户端
CopyOnWriteArrayList<Channal> clients=new CopyOnWriteArrayList<Channal>();
//客户端编号
int num=1;
while(true) {
Socket client=server.accept();
Channal channal=new Channal(client,clients,num);
clients.add(channal);
new Thread(channal).start();
num++;
}
}
}
//一个客户端
class Channal implements Runnable{
DataInputStream data=null;
DataOutputStream dataOut=null;
//判断运行状态
boolean isRunning=true;
Socket client;
//储存客户端的动态数组
CopyOnWriteArrayList<Channal> clients;
//每个客户端的编号
int num;
//构造函数
public Channal(Socket client,CopyOnWriteArrayList<Channal> clients,int num) {
this.client=client;
this.clients=clients;
this.num=num;
}
//辅助函数,根据编号获取相应的客户
private Channal getChannal(int num) {
Channal pre=null;
for( Channal c:clients) {
if(c.num==num) {
pre=c;
break;}
}
return pre;
}
//接受消息
public String receive() {
String s="";
try {
data = new DataInputStream(client.getInputStream());
s = data.readUTF();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
isRunning=false;
}
return s;
}
//发送消息
public void send(String s,int num) {
DataOutputStream dataOut=null;
try {
dataOut = new DataOutputStream(client.getOutputStream());
dataOut.writeUTF("第"+num+"个人"+":"+s);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
isRunning=false;
}
}
@Override
public void run() {
// TODO 自动生成的方法存根
while(isRunning) {
String s="";
s=receive();
//私聊
if(s.startsWith("@")) {
//私聊的格式——>@2:XXXX
int i=Integer.valueOf(s.substring(1, 2));
getChannal(i).send(s.substring(3),num);
continue;
}
//群聊
for(Channal client:clients) {
if(num!=client.num)
client.send(s,num);
}
}
//释放资源
Close.close(client,data,dataOut);
}
}
接着创建客户端:
import java.io.BufferedReader;
import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
import java.net.UnknownHostException;
public class client {
public static void main(String[] args){
//创建客户端
System.out.println("启动客户端");
Socket client=null;
try {
client = new Socket("localhost",9999);
} catch (UnknownHostException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
new Thread(new Send(client)).start();
new Thread(new Receive(client)).start();
}
}
客户端中的send方法:
import java.io.BufferedReader;
import java.io.DataOutputStream;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.Socket;
public class Send implements Runnable{
DataOutputStream data;
BufferedReader br;
//构造函数
public Send(Socket client) {
try {
br=new BufferedReader(new InputStreamReader(System.in));
data=new DataOutputStream(client.getOutputStream());
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
@Override
public void run() {
boolean isRunning=true;
while(isRunning) {
String s="";
try {
s = br.readLine();
data.writeUTF(s);
data.flush();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
Close.close(data,br);
isRunning=false;
}
}
}
}
客户端中的Receive方法:
import java.io.DataInputStream;
import java.io.IOException;
import java.net.Socket;
public class Receive implements Runnable{
DataInputStream dataIn;
Socket client;
boolean isRunning=true;
//构造函数
public Receive(Socket client) {
this.client=client;
try {
dataIn=new DataInputStream(client.getInputStream());
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
@Override
public void run() {
// TODO 自动生成的方法存根
while(isRunning) {
try {
String s=dataIn.readUTF();
System.out.println(s);
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
Close.close(dataIn,client);
}
}
}
}
封装释放资源的方法:
import java.io.Closeable;
import java.io.IOException;
public class Close {
public static void close(Closeable...closeables) {
for(Closeable Close:closeables)
try {
Close.close();
} catch (IOException e) {
// TODO 自动生成的 catch 块
e.printStackTrace();
}
}
}