java-socket編程

先前有篇博文專門寫了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;
	}
    }



發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章