import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
/**
* 聊天服務器,支持羣聊,相當於openfire
*
* 有一個新用戶,會建一個socket連接,會啓一個線程
* socket連接只有在用戶退出的時候纔會關閉。
* @author pjy
*
*/
public class SocketServer {
private static final int PORT = 15898;//大於1024
private List<Socket> socketList = new ArrayList<Socket>();
private ServerSocket server = null;
private ExecutorService threadPool = null; //thread pool
public static void main(String[] args) {
new SocketServer();
}
public SocketServer() {
try {
//如果有客戶端發信息到15898這個端口,操作系統會把信息交給我們這個程序處理
server = new ServerSocket(PORT);
threadPool = Executors.newCachedThreadPool(); //create a thread pool
System.out.println("server start ...");
//socketClient代表的是與某一個客戶端的連接
Socket socketClient = null;
while(true) {
//客戶端跟我們服務器端建立連接之後,創建socketClient對象
socketClient = server.accept();
socketList.add(socketClient);
// System.out.println("有"+mList.size()+"個連接 ");
System.out.println("有連接 ");
threadPool.execute(new Service(socketClient)); //start a new thread to handle the connection
}
}catch (Exception e) {
e.printStackTrace();
}
}
class Service implements Runnable {
private Socket socketClient;
private BufferedReader in = null;
private String msg = "";
public Service(Socket socketClient) {
this.socketClient = socketClient;
try {
in = new BufferedReader(new InputStreamReader(
socketClient.getInputStream()));
msg = "user" +this.socketClient.getInetAddress() + "客戶端個數:"
+socketList.size()+"線程id:"+Thread.currentThread().getId();
this.sendmsg();
} catch (IOException e) {
e.printStackTrace();
}
}
@Override
public void run() {
// TODO Auto-generated method stub
try {
while(true) {
if((msg = in.readLine())!= null) {
if(msg.equals("exit")) {
System.out.println("有客戶端退出");
socketList.remove(socketClient);
in.close();
msg = "user:" + socketClient.getInetAddress()
+ "exit total:" + socketList.size();
socketClient.close();
this.sendmsg();
break;
} else {
//狀態碼|消息類型|消息json數據
msg = "{'user ip':'"+socketClient.getInetAddress() + "','msg':'" + msg+"'} ";
System.out.println("sever 收到"+msg);
this.sendmsg();
}
}
}
} catch (Exception e) {
e.printStackTrace();
}
}
//socket對象在內存中。客戶端不發請求,服務器端也可以主動向客戶端發數據
//http的特點是必須是客戶端先發請求,服務器端才能返加數據。
public void sendmsg() {
int socketClinetNumber =socketList.size();
//給所有的客戶端發數據,說明1是推送 2,是羣聊
for (int index = 0; index < socketClinetNumber; index ++) {
//Socket產生一個ip[tcp[msg]]
Socket socketClient = socketList.get(index);
PrintWriter pout = null;
try {
pout = new PrintWriter(new BufferedWriter(
new OutputStreamWriter(
socketClient.getOutputStream())),true);
pout.println(msg);
}catch (IOException e) {
e.printStackTrace();
}
}
}
}
}