- 服务器套接字和连接套接字的区别
其实看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的过程。
下面是一个套接字同时打开的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
发表评论