package network.tcpclient; import java.io.*; import java.net.*; import java.util.*; public class SimpleClient { public static void main(String[] args) { if (args.length != 2) { System.err.println("Usage: java network.tcpclient.SimpleClient host port"); return ; } String host = args[0]; int port = Integer.parseInt(args[1]); new Thread(new TcpClient(host, port)).start(); } } class TcpClient implements Runnable { Socket socket; String host; int port; public TcpClient(String host, int port) { this.host = host; this.port = port; } public void run() { try { socket = new Socket(host, port); InputStream inFromHost = socket.getInputStream(); OutputStream outToHost = socket.getOutputStream(); InputStream inFromUser = System.in; OutputStream outToUser = System.out; byte[] buffer = new byte[1024]; int count = 0; for (;;) { count = inFromUser.read(buffer); if (count <= 0) // EOF indicates a quit break; outToHost.write(buffer, 0, count); count = inFromHost.read(buffer); outToUser.write(buffer, 0, count); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (socket != null) { socket.close(); } } catch (IOException e) { e.printStackTrace(); } } } }
package network.tcpserver; import java.io.*; import java.util.*; import java.net.*; public class EchoServer { public static void main(String[] args) { try { new Thread(new TcpServer(8989)).start(); } catch (IOException e) { e.printStackTrace(); } } } class TcpServer implements Runnable { private ServerSocket serverSocket; // constructor public TcpServer(int port) throws IOException { this.serverSocket = new ServerSocket(port); } public void run() { for (;;) { try { Socket socket = serverSocket.accept(); new Thread(new EchoConnectionHandler(socket)).start(); } catch (IOException e) { e.printStackTrace(); } } // try } // run } abstract class ConnectionHandler implements Runnable { private Socket socket; // constructor public ConnectionHandler(Socket socket) { this.socket = socket; } public void run() { handleConversation(socket); } // should be overridden by derived classes abstract public void handleConversation(Socket socket); } class EchoConnectionHandler extends ConnectionHandler { public EchoConnectionHandler(Socket socket) { super(socket); } public void handleConversation(Socket socket) { try { InputStream in = socket.getInputStream(); OutputStream out = socket.getOutputStream(); byte[] buffer = new byte[8192]; int count; while ((count = in.read(buffer))>=0) { out.write(buffer, 0, count); out.flush(); } } catch (IOException e) { e.printStackTrace(); } finally { try {socket.close();} catch (IOException e) {} } } }
後記:java
1. 增長socket.getLocalPort()方法後,打印信息以下:網絡
root@localhost:/home/James/mypro/Network/TcpServer# java network.tcpserver.EchoServersocket
Server using port: 8989tcp
Connection using port: 8989ui
root@localhost:/home/James/mypro/Network/TcpClient# java network.tcpclient.SimpleClient localhost 8989this
Connection using port: 60822spa
hello.net
hello3d
2. 默認狀況下,tcp server監聽全部本地的IP地址。以下是客戶端的打印:code
root@localhost:/home/James/mypro/Network/TcpClient# java network.tcpclient.SimpleClient localhost 8989
Connection using port: 60822
hello
hello
root@localhost:/home/James/mypro/Network/TcpClient# java network.tcpclient.SimpleClient 10.0.0.28 8989
Connection using port: 36185
hello
hello
root@localhost:/home/James/mypro/Network/TcpClient# java network.tcpclient.SimpleClient 10.0.0.29 8989
Connection using port: 37042
hello
hello
3. 一個TCP socket用(src ip, src port, dst ip, dst port)來標識。
以下,增長如下代碼後
public void run() { for (;;) { try { Socket socket = serverSocket.accept(); System.out.println("Local host: " + socket.getLocalAddress()); System.out.println("Local port: " + socket.getLocalPort()); System.out.println("Remote host is: " + socket.getInetAddress()); System.out.println("Remote port is: " + socket.getPort()); new Thread(new EchoConnectionHandler(socket)).start(); } catch (IOException e) { e.printStackTrace(); } } // try } // run
運行結果:
root@localhost:/home/James/mypro/Network/TcpServer# java network.tcpserver.EchoServer
Server using port: 8989
Server reuse address: true
Local host: /127.0.0.1
Local port: 8989
Remote host is: /127.0.0.1
Remote port is: 38108
4. accept獲得的socket繼承listen socket的各類屬性,但並不繼承local address ,結果以下:
root@localhost:/home/James/mypro/Network/TcpServer# java network.tcpserver.EchoServer
listen socket using address: 0.0.0.0/0.0.0.0:8989
listen socket using port: 8989
listen socket reuse address: true
Local host: /127.0.0.1:8989
Local port: 8989
Remote host is: /127.0.0.1
Remote port is: 33309
增長的代碼段是:
public TcpServer(int port) throws IOException { this.serverSocket = new ServerSocket(port); System.out.println("listen socket using address: " + serverSocket.getLocalSocketAddress()); System.out.println("listen socket using port: " + serverSocket.getLocalPort()); System.out.println("listen socket reuse address: " + serverSocket.getReuseAddress()); }
0.0.0.0表示此socket只綁定端口,監聽本機上全部網絡全部IP,具體和哪一個ip連,由路由器決定。參考以下博客:
http://hi.baidu.com/cpuramdisk/item/2e46c45f35fc5d3d33e0a90d