平時開發中會經常接觸到Socket,其使用也不複雜,在阻塞Socket中,主要是了解什麼操作會導緻阻塞。serverSocket的accept方法會一直阻塞直到有用戶端Socket進入,處理時最好是另開一個線程給它。
把聊天系統簡單化,一個伺服器是必需的,下面稱之為A,用來傳輸兩個進行聊天的用戶端之間的消息,下面稱為B和C。B需要一個标志位,用于檢查是否剛登入,若是,自動發送自己的ID和消息給A,告訴A我已上線,然後A中需要有一個客戶清單用來儲存線上的客戶ID。接下來B發送消息給C前,要把C的ID也發送給A,這樣才能進行B和C之間的正常通信。當然,A還要先根據C的ID檢查客戶清單中是否有C,已确定C是否線上上;若C不線上上就要告訴B,若在,B和C通信建立,可以開始聊天了。
===========================================================傳說中的分界線=============================================================
伺服器代碼:
package server;
import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.HashMap;
public class ServerChat {
private static ServerSocket server;
private static volatile HashMap
userQueue = new HashMap
();
public ServerChat(int port, int backlog) {
try {
server = new ServerSocket(port);
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
/**
* 使用者聊天的核心方法
*/
private static void processChat() {
// boolean shutdown = false;
// String received = null;
System.out.println("等待使用者接入。。。");
try {
while (true) {
Socket client = server.accept();
System.out.println("已有使用者接入,等待資訊。。。");
new Thread(new Runnable() {
TransferMsgThread tranUserInfo = new TransferMsgThread(
client);
String send = null;
boolean firstTime = true;
String userID = null;
String friendID = null;
@Override
public void run() {
System.out.println("即将進入while循環。。。");
while (true) {
send = tranUserInfo.sendMessage();
// 客戶上線時,背景主動發送消息通知伺服器客戶已上線
if (send != null) {
System.out.println("info content :" + send);
if (firstTime
&& send.substring(send.indexOf(':') + 1)
.equalsIgnoreCase("I am onLine")) {
userID = send.substring(0,
send.indexOf(":"));
send = send.substring(send.indexOf(":") + 1);
// 将線上使用者添加進表中
if (userQueue.size() == 0
|| userQueue.get(userID) == null) {
userQueue.put(userID, client);
}
firstTime = false;
System.out.println("userQueue get "
+ userQueue.get(userID));
} else {
friendID = send.substring(0,
send.indexOf(":"));
System.out.println("friendID == "
+ friendID);
send = send.substring(send.indexOf(":") + 1);
Socket friend = (Socket) userQueue
.get(friendID);
if (friend == null) {
tranUserInfo.receiveMessage("對方未上線!");
} else {
if (send.equals("shutdown")) {
// shutdown = true;
// break;
}
TransferMsgThread tranFriendInfo = new TransferMsgThread(
friend);
tranFriendInfo.receiveMessage(userID
+ ": " + send);
}
}
} else {
if (firstTime) {
firstTime = false;
System.out.println("message is null !");
}
}
}
}
}).start();
}
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
// closeConnect();
}
protected static void closeConnect() {
try {
server.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void main(String[] args) {
new ServerChat(8899, 100).processChat();
}
}
package server;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.net.Socket;
public class TransferMsgThread {
private volatile String message;
private Socket client;
public TransferMsgThread(Socket client) {
this.client = client;
}
public String sendMessage() {
try {
message = sendMessageToOtherClient(client);
} catch (IOException e) {
e.printStackTrace();
}
System.out.println("message == " + message);
return message;
}
public void receiveMessage(String msg) {
try {
getMessageFormOtherClient(client, msg);
} catch (IOException e) {
e.printStackTrace();
}
}
protected void getMessageFormOtherClient(Socket client, String msg)
throws IOException {
BufferedWriter writer;
writer = new BufferedWriter(new OutputStreamWriter(
client.getOutputStream(), "UTF-8"));
writer.write(msg + "EOF");
writer.newLine();
writer.flush();
}
protected static String sendMessageToOtherClient(Socket client)
throws IOException {
BufferedReader reader;
reader = new BufferedReader(new InputStreamReader(
client.getInputStream(), "UTF-8"));
StringBuffer msg = new StringBuffer();
String tmp = null;
int index = -1;
while ((tmp = reader.readLine()) != null) {
if ((index = tmp.indexOf("EOF")) != -1) {
tmp = tmp.substring(0, index);
msg.append(tmp);
System.out.println("break out while!");
break;
}
msg.append(tmp);
}
return msg.toString();
}
}
用戶端代碼:
package Test;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.UnsupportedEncodingException;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
public class Client {
private String host;;
private int port;;
private Socket client;
public Client() {
this( "127.0.0.1", 8899);
}
public Client(String host, int port) {
this.host = host;
this.port = port;
try {
client = new Socket(host, port);
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public void writeInfo(String info) {
BufferedWriter writer = null;
try {
writer = new BufferedWriter( new OutputStreamWriter(client.getOutputStream(),
"UTF-8"));
writer.write(info);
writer.newLine();
writer.flush();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// finally {
// if (writer != null) {
// try {
// writer.close();
// } catch (IOException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
// }
// }
}
public String readInfo() throws SocketTimeoutException{
String info = null;
BufferedReader br = null;
try {
br = new BufferedReader(new InputStreamReader(
client.getInputStream(), "UTF-8"));
// client.setSoTimeout(5 * 1000);
StringBuffer sb = new StringBuffer();
String temp;
int index;
while((temp = br.readLine()) != null) {
if((index = temp.indexOf("EOF")) != -1) {
sb.append(temp.substring(0, index));
break;
}
sb.append(temp);
}
info = sb.toString();
} catch (UnsupportedEncodingException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// finally {
// if(br != null) {
// try {
// br.close();
// } catch (IOException e) {
// e.printStackTrace();
// }
//
// }
// }
return info;
}
public void clientDown() {
if(client != null) {
try {
client.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
package Test;
import java.net.SocketTimeoutException;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.Scanner;
import java.util.Timer;
import java.util.TimerTask;
public class MainTest {
private static Client client;
private static SimpleDateFormat format;
public static void main(String[] args) {
System.out.println("start client");
Scanner input = new Scanner(System.in);
String line = null;
System.out.println("請輸入你的ID:");
line = input.nextLine();
client = new Client();
client.writeInfo(line + ":I am onLine" + "EOF");
new Thread() {
public void run() {
while(true) {
String info;
try {
info = client.readInfo();
if(info != null) {
System.out.println(info);
}
} catch (SocketTimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};
}.start();
System.out.println("請輸入你朋友的ID:");
String id = input.nextLine();
System.out.println("聊天開始:");
new Thread() {
public void run() {
while(true) {
String line = input.nextLine();
client.writeInfo(id + ":" + line + "EOF");
if(line.equalsIgnoreCase("shutdown")) {
break;
}
}
};
}.start();
// Timer timer = new Timer(true);
//
// TimerTask task = new TimerTask() {
//
// public void run() {
// plane();
// }
//
// };
//
// timer.schedule(task, 2 * 1000, 5 * 1000);
//
// try {
// Thread.sleep(50 * 1000);
// } catch (InterruptedException e) {
// // TODO Auto-generated catch block
// e.printStackTrace();
// }
}
public static void plane() {
System.out.println("client plane starting");
format = new SimpleDateFormat(
"yy-MM-dd HH:mm:ss");
client = new Client();
client.writeInfo(format.format(new Date()));
try {
System.out.println("info show by client,form server"
+ client.readInfo());
} catch (SocketTimeoutException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
// client.clientDown();
System.out.println("client real in the end!");
}
}