网络编程中的若干盲点

= 1649
  • 服务器套接字和连接套接字的区别

        其实看UNP的时候,我根本没有仔细思考这两个概念的区别。然后学习Java网络编程的时候就很好奇,Java的ServerSocket和Socket设计的初衷是什么呢?其实在Socket的本地api并没有对这两者做很大区分。事实上,他们都是使用socket()调用创建的,所以他们的内存布局应该都是一样的。两者的正真区别体现在listen调用和connect调用(两者都可以使用bind调用,虽然连接套接字的很少会这样使用)。一个非常直观的概念是服务器套接字是一个由本地端口和本地ip地址组成的二元组(严格来说还包含协议),而连接套接字这是由本地端口、本地ip地址、远程端口和远程ip地址组成的四元组。

  • 主动连接套接字也可使用bind绑定本地ip和端口

        客户端socket也可以主动绑定ip地址和端口,一个很常见的应用就是主动模式的ftp协议。ftp服务器的数据连接socket是主动绑定的20端口,然后主动连接客户端的数据端口。在多个回话并行的情况下,多个连接socket的端口都是20,但是由于客户ip和端口不同,所以并不会冲突。

  • 连接套接字可以同时打开

        在大名鼎鼎的tcp状态转移图中,有一个非常比较奇怪的同时打开转移路径。简而言之,就是两个连接套接字主动相互连接,完全没有listen的过程。

tcp_state_machine

        下面是一个套接字同时打开的demo

package nonblock;
import java.net.*;
import java.nio.channels.*;
import java.nio.charset.*;
import java.nio.*;
import java.io.*;
import java.util.*;


public class SimuOpen {
	private Socket sock1 = null, sock2 = null;
	private int port1 = 50000, port2 = 50001;
	private String host = "localhost";
	
	public SimuOpen() throws IOException{

	}
	
	public static void main(String[] args) throws IOException {
		new SimuOpen().work();
	}
	
	public void work(){
		Worker work1 = new Worker(port1, port2);
		Worker work2 = new Worker(port2, port1);
		work1.start();
		work2.start();
		
	}

	

	public class Worker extends Thread{
		private int localport = 0;
		private int remoteport = 0;
		public Worker(int localport, int remoteport){
			this.localport = localport;
			this.remoteport = remoteport;
		}
		
		
		private PrintWriter getWriter(Socket socket)throws IOException{
			OutputStream socketOut = socket.getOutputStream();
			return new PrintWriter(socketOut, true);
		}
		private BufferedReader getReader(Socket socket)throws IOException {
			InputStream socketIn = socket.getInputStream();
			return new BufferedReader(new InputStreamReader(socketIn));		
		}
		
		public void run(){
			while(true){
				try {
					Socket socket = new Socket();
					socket.bind(new InetSocketAddress("127.0.0.1",localport));
					socket.connect(new InetSocketAddress("127.0.0.1",remoteport));
					BufferedReader br = getReader(socket);
					PrintWriter pw = getWriter(socket);
					String msg = "hello world!" + socket.getLocalPort();
					pw.println(msg);
					System.out.println(socket.getLocalPort() + ":" + br.readLine());
				} catch (IOException e) {
					// TODO Auto-generated catch block
					//e.printStackTrace();
				}

			}
		}
	}
}

        输出如下:

  • 50001:hello world!50000
  • 50000:hello world!50001

发表评论