客户端之间通信: 实际上两个客户端不能直接通信,要借助服务器来做为中转站,才能实现双方通信。
一个客户端发送数据到服务器,服务器将数据发送给(所有连接上服务器的)客户端,这样客户端之间实现了通信。
服务器的代码:
public class PcService {
private static final int SERVICEPORT=10086;
private static ArrayList<Socket> mClientList=new ArrayList<Socket>(); //记录连接上服务器的客户端
private ExecutorService mExecutorService; //创建线程池来管理
private ServerSocket serverSocket;
public static void main(String[] args) {
new PcService();
}
public PcService() {
try {
serverSocket=new ServerSocket(SERVICEPORT);
mExecutorService=Executors.newCachedThreadPool();
Socket clientSocket=null;
while(true){ //一接受到客户端发送来的数据,立刻将信息转发给所有连接在线的客户端
clientSocket=serverSocket.accept();
mClientList.add(clientSocket);
mExecutorService.execute(new ThreadServer(clientSocket));
}
}
catch (Exception e) {
e.printStackTrace();
}
}
static class ThreadServer implements Runnable{
PrintWriter printWriter;
BufferedReader bufferedReader;
String message;
Socket socket;
public ThreadServer(Socket socket) throws IOException {
this.socket=socket;
bufferedReader=new BufferedReader(new InputStreamReader(socket.getInputStream()));
message=this.socket.getInetAddress()+"";
sendMessageToClient();
}
public void run() {
try {
while((message=bufferedReader.readLine())!=null){
if(message.trim().equals("exit")){//当一个客户端退出时
mClientList.remove(socket);
bufferedReader.close();
printWriter.close();
socket.close();
sendMessageToClient();
break ;
}
else{
message=socket.getInetAddress()+"";
sendMessageToClient();
}
}
}
catch (Exception e) {
e.printStackTrace();
}
}
//发送消息给每一个连接的客户端
private void sendMessageToClient(){
try {
for(Socket client:mClientList){
printWriter=new PrintWriter(client.getOutputStream());
printWriter.println( message );
}
}
catch (Exception e) {
e.printStackTrace();
}
}
}
}
监控TCP的状态: 心跳包
做法:一个单独线程(心跳线程),来维护tcp的连接。
每隔一个时间就向服务器/客户端发送一段连接信息,当对方接受到后马上回复对方。然后设置一个超时时间
,过个时间就反复发几次。如果没有收到回复,则判定tcp断开了。
用心跳包来维护连接,在发送心跳包异常时,可以认为对方短线,
或者指定时间超时后,未收到对方的心跳响应,也认为是对方短线。
或者就是Send的时候会直接报异常,可以直接认为是掉线了。