<a target="_blank" href="http://vaero.blog.51cto.com/4350852/893837">Java Socket基礎(一)</a>
<a target="_blank" href="http://vaero.blog.51cto.com/4350852/893844">Java Socket基礎(二)</a>
2.3)LinkServer2.java
/**
* 開啟伺服器,長連接配接各個Socket,主動發送資料
*
* @author Join
*/
public class LinkServer2 extends Thread {
/** 服務端口 */
private int port;
/** 服務套接字 */
private ServerSocket mServerSocket;
/** 伺服器監聽接口 */
private OnLinkServerListener listener;
/** 用戶端套接字集合 */
private ArrayList<Socket> clientList;
/** 用戶端的輸出流集合 */
private ArrayList<ObjectOutputStream> osList;
public LinkServer2(int port) {
this.port = port;
clientList = new ArrayList<Socket>();
osList = new ArrayList<ObjectOutputStream>();
}
@Override
public void run() {
try {
mServerSocket = new ServerSocket(port); // 建立本地特定端口伺服器套接字
Socket client = null;
while (true) {
client = mServerSocket.accept(); // 接收連接配接的套接字
if (null != listener) {
listener.onClientConnected(client.getInetAddress());
}
clientList.add(client);
osList.add(new ObjectOutputStream(client.getOutputStream())); // 增加連接配接的輸出流
}
} catch (BindException e) { // 端口使用中
if (null != listener) {
listener.onBindException();
} catch (IOException e) {
e.printStackTrace();
}
/** 發送序列化對象 */
public void sendObj(Object obj) {
/* 這個判斷非必需的,記得就好 */
if (null != obj && !isSerializable(obj))
throw new IllegalArgumentException(
"Object needs to implement java.io.Serializable!");
ObjectOutputStream out = null;
for (int i = 0; i < osList.size(); i++) {
try {
out = osList.get(i);
out.writeObject(obj);
out.flush();
/* 發送null時,表示退出了 */
if (null == obj) {
if (null != listener) {
listener.onExited(clientList.get(i).getInetAddress());
}
closeSocket(i); // 關閉目前Socket
i--; // 少了個記得減
} catch (SocketException e) { // Connection reset
listener.onSocketException(clientList.get(i)
.getInetAddress());
closeSocket(i); // 關閉目前Socket
i--; // 少了個記得減
} catch (IOException e) {
e.printStackTrace();
/** 關閉某個Socket */
private void closeSocket(int index) {
osList.get(index).close();
osList.remove(index);
clientList.get(index).close();
clientList.remove(index);
} catch (IOException e1) {
e1.printStackTrace();
/** 判斷是否序列化 */
private boolean isSerializable(Object obj) {
Class<?>[] cls = obj.getClass().getInterfaces();
for (Class<?> clazz : cls) {
if (clazz.getName().equals(Serializable.class.getName()))
return true;
return false;
/** 設定伺服器監聽接口 */
public void setOnLinkServerListener(OnLinkServerListener listener) {
this.listener = listener;
}
<b>二、短連接配接通信</b>
用戶端請求一次,建立一次Socket,完成後即可關閉。服務端通過accept()等待。
<b>1</b><b>)對象消息</b>
用戶端發送對象,服務端接受對象,很簡單的例子。
1.1)EasyClient.java
* 每次連接配接伺服器發送一個消息
*
public class EasyClient {
/** 套接字位址 */
private SocketAddress address;
/** 逾時時間 */
private int timeout;
/** 用戶端監聽接口 */
private OnClientListener listener;
public EasyClient(String host, int port, int timeout) {
this.address = new InetSocketAddress(host, port);
this.timeout = timeout;
/**
* 發送一個消息
*
* @param obj 對象消息
*/
public boolean sendMessage(Object obj) {
boolean result = false;
Socket socket = null;
try {
socket = new Socket();
socket.connect(address, timeout);
if (null != listener) {
listener.onConnected();
}
result = sendMessage(socket, obj);
} catch (ConnectException e) { // 拒絕連接配接
listener.onConnectException();
} catch (SocketTimeoutException e) { // 連接配接逾時
listener.onTimeoutException();
} catch (IOException e) {
e.printStackTrace();
} finally {
try {
if (null != socket) {
socket.close(); // 關閉Socket
socket = null;
}
} catch (IOException e) {
e.printStackTrace();
}
return result;
/** 通過Socket發送obj消息 */
private boolean sendMessage(Socket socket, Object obj) {
ObjectOutputStream os = null;
os = new ObjectOutputStream(socket.getOutputStream());
os.writeObject(obj);
os.flush();
listener.onMessageSent(obj);
result = true;
} catch (SocketException e) { // Connection reset
listener.onSocketException();
if (null != os) {
os.close();
/** 設定用戶端監聽接口 */
public void setOnClientListener(OnClientListener listener) {
this.listener = listener;
1.2)EasyServer.java<b></b>
public class EasyServer extends Thread {
private OnServerListener listener;
public EasyServer(int port) {
this.port = port;
mServerSocket = new ServerSocket(port); // 建立本地特定端口伺服器套接字
Socket socket = null;
while (true) {
socket = mServerSocket.accept(); // 接收連接配接的套接字
receiveMessage(socket); // 接收socket處理消息
} catch (BindException e) { // 端口使用中
listener.onBindException();
/** 接收處理每個Socket資訊 */
private void receiveMessage(Socket socket) {
ObjectInputStream is = null;
is = new ObjectInputStream(new BufferedInputStream(
socket.getInputStream()));
Object obj = is.readObject();
listener.onReceive(socket.getInetAddress(), obj);
listener.onSocketException(socket.getInetAddress());
} catch (ClassNotFoundException e) {
if (null != is) {
is.close();
socket.close();
public void setOnServerListener(OnServerListener listener) {
<b>三、後記</b>
恩,哦,socket還有個比較常用的是setSoTimeout(),在read()阻塞逾時會報SocketTimeoutException,catch住處理即可。
ps:老遇到8W備援字元,拆着拆着就三個了==!
<a href="http://down.51cto.com/data/2360758" target="_blank">附件:http://down.51cto.com/data/2360758</a>
本文轉自winorlose2000 51CTO部落格,原文連結:http://blog.51cto.com/vaero/893847,如需轉載請自行聯系原作者