先前有篇博文專門寫了socket的基本概念,這裏用java來實現簡單的server-client的socket數據傳輸。
server端
/**
* socket服務端
*
* @author peter_wang
* @create-time 2014-8-30 下午3:25:27
*/
public class Server {
public static void main(String args[])
throws IOException {
int port = 8888;
ServerSocket server = new ServerSocket(port);
while (true) {
// 開始接受socket請求
Socket socket = server.accept();
// 建立新線程處理新進的socket請求
new Thread(new Task(socket)).start();
}
}
/**
* 處理Socket請求的異步任務
*/
static class Task
implements Runnable {
private Socket mSocket;
public Task(Socket socket) {
this.mSocket = socket;
}
public void run() {
try {
handleSocket();
}
catch (Exception e) {
e.printStackTrace();
}
}
/**
* 跟客戶端Socket進行通信
*
* @throws Exception
*/
private void handleSocket()
throws Exception {
BufferedReader br = new BufferedReader(new InputStreamReader(mSocket.getInputStream(), "UTF-8"));
StringBuilder sb = new StringBuilder();
String temp;
int index;
while ((temp = br.readLine()) != null) {
// 遇到eof時結束接收
if ((index = temp.indexOf("eof")) != -1) {
System.out.println(temp);
sb.append(temp.substring(0, index));
break;
}
sb.append(temp);
}
System.out.println("data from client: " + sb);
// 寫操作
Writer writer = new OutputStreamWriter(mSocket.getOutputStream());
writer.write("Hello Client.");
writer.write("eof\n");
writer.flush();
writer.close();
br.close();
mSocket.close();
}
}
}
client端
/**
* socket客戶端
*
* @author peter_wang
* @create-time 2014-8-30 下午4:13:11
*/
public class Client {
public static void main(String args[])
throws Exception {
String host = "127.0.0.1"; // 本地地址
int port = 8888;
// 與服務端建立連接
Socket client = new Socket(host, port);
Scanner sc = new Scanner(System.in);
String str = sc.nextLine();
System.out.println("輸入的內容爲:" + str);
// 建立連接後就可以往服務端寫數據了
Writer writer = new OutputStreamWriter(client.getOutputStream(), "UTF-8");
writer.write(str);
writer.write("eof\n");
writer.flush();
// 寫完以後進行讀操作
BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream()));
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);
}
System.out.println("from server: " + sb);
writer.close();
br.close();
client.close();
}
}
1.用了eof做完讀寫結束標識。
2.BufferedReader提高了IO效率,用異步提前準備好數據存儲到內存,讀取直接從內存讀,如果數據來源於磁盤IO或網絡IO,速度將快很多,磁盤讀取和內存讀取的速度對比參見這篇文章。
3.server和client之間數據傳輸需要統一編碼,防止亂碼。
4.源碼分析,server端的new ServerSocket(port)實現了new socket、bind、listener功能
public void bind(SocketAddress endpoint, int backlog) throws IOException {
if (isClosed())
throw new SocketException("Socket is closed");
if (!oldImpl && isBound())
throw new SocketException("Already bound");
if (endpoint == null)
endpoint = new InetSocketAddress(0);
if (!(endpoint instanceof InetSocketAddress))
throw new IllegalArgumentException("Unsupported address type");
InetSocketAddress epoint = (InetSocketAddress) endpoint;
if (epoint.isUnresolved())
throw new SocketException("Unresolved address");
if (backlog < 1)
backlog = 50;
try {
SecurityManager security = System.getSecurityManager();
if (security != null)
security.checkListen(epoint.getPort());
getImpl().bind(epoint.getAddress(), epoint.getPort());
getImpl().listen(backlog);
bound = true;
} catch(SecurityException e) {
bound = false;
throw e;
} catch(IOException e) {
bound = false;
throw e;
}
}
client端的new Socket(host, port)實現了new socket和connect功能
private Socket(SocketAddress address, SocketAddress localAddr,
boolean stream) throws IOException {
setImpl();
// backward compatibility
if (address == null)
throw new NullPointerException();
try {
createImpl(stream);
if (localAddr != null)
bind(localAddr);
if (address != null)
connect(address);
} catch (IOException e) {
close();
throw e;
}
}