平时开发中会经常接触到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!");
}
}