初探Tomcat源码 (2) —— Socket

来源:互联网 发布:java初学者项目案例 编辑:程序博客网 时间:2024/05/22 02:19

        网络中进程之间的通信,Request和Response的交互就是通过Socket来是实现的。这需要唯一地标识一个进程。

        在本地可以通过进程PID来唯一标识一个进程,但是在网络需要用另一种方式标识:利用三元组(IP地址协议端口)来标识网络的进程。

网络层的“ip地址”可以唯一标识网络中的主机,而传输层的“协议+端口”可以唯一标识主机中的应用程序(进程)。

因此: Socket = IP Address + TCP/UDP + Port

 

        Socket起源于Unix,而Unix/Linux基本哲学之一就是“一切皆文件”,都可以用“open>write/read>close”模式来操作。Socket就是该模式的一个实现,socket算是一种特殊的文件,而socket函数就是对其进行操作(读/写IO、打开、关闭)。

        Socket是支持TCP/IP的网络通信的基本操作单元,可以看做是不同主机之间的进程进行双向通信的端点,简单的说就是通信的两方的一种约定,用套接字中的相关函数来完成通信过程。      使用套接字通信,简单来说就是通过Socket向网络发出请求或者应答网络请求

 

实现通信的Socket分为两种:客户端Socket 和 服务器端ServerSocket。

简单来说,ServerSocket和Socket在创建的时候先绑定IP和端口;

1、客户端创建Socket就会向该端口发送连接请求,然后拼装请求内容输入流;

2、服务器端ServerSocket监听Socket.accept(),客户连接后,接收一个socket对象,先read()处理后,再write()返回;

3、此时客户端Socket.read()读取返回信息,最后关闭。

 

客户端不需要指定打开的端口,通常临时的、动态的分配一个1024以上的端口。

客户端Socket 和 服务器端ServerSocket,都是【open>write/read>close】模式,在下面的例子中能体现出来。


java.net.Socket 

一个socket是网络连接的一个端点,两端的应用程序可以通过Socket请求连接,发送和接收字节流来通信。

 

        Socket socket = new Socket(InetAddress.getByName("localhost"), 8000);

        PrintWriter out = null;

        BufferedReader in = null;

        try {

            out = new PrintWriter(new BufferedWriter(

newOutputStreamWriter(socket.getOutputStream())),true);

            out.println("Hello Server,I want something.");   

            // 

            in = new BufferedReader(

newInputStreamReader(socket.getInputStream()));

            System.out.println("Response : " +in.readLine());   

        } finally {

            System.out.println("close ClientSocket.");

            socket.close();

            out.close();

            in.close();

        }


java.net.ServerSocket

ServerSocket监听IP地址和端口号,需要随时响应客户端的Socket,一旦接收到连接Request,就会创建一个Socket实例来处理客户请求。

另外backLog是请求的长度,超出就拒绝接收。

创建:ServerSocket(intport,int backLog,java.net.InetAddress bindingAddress);

 

        PrintWriter out = null;

        BufferedReader in = null;

        ServerSocket s = new ServerSocket(8000);   

        Socket socket = s.accept();                    //  阻塞,等待客户的连接请求

        System.out.println("Accept the Client: " + socket);

        try {

            in = new BufferedReader(           

newInputStreamReader(socket.getInputStream()));

            System.out.println("Request : " + in.readLine());

            // 

            out = new PrintWriter(new BufferedWriter(

newOutputStreamWriter(socket.getOutputStream())),true);

            out.println("Welcome to Server");

        } finally {

            System.out.println("close ServerSocket.");

            socket.close();

            s.close();

            out.close();

            in.close();

        }

 

现在先启动SocketServer的代码,能看到程序阻塞了,是在等待socket的请求。

然后在启动SocketClient的代码,这时候SocketServer端打印出客户的Socket内容,并且结束程序。服务器端打印客户端的信息,客户端打印服务器端的返回信息。

我们也可以直接用浏览器访问 http://localhost:8000,SocketServer同样能监听到,并且做出响应。

 

另外,在实际的网络环境里,同一时间只对一个用户服务是不可行的。一个优秀的网络服务程序必须能够同时响应多个客户端的连接请求。

一般做法:主程序监听一端口,等待客户接入;同时构造一个线程类,准备接管会话。当一个Socket会话产生后,将这个会话交给线程处理,然后主程序继续监听

具体方案,可以参考Connector和Processor。

原创粉丝点击