Socket俗称套接字,用于描述IP地址和端口,是一个通信链的句柄。应用程序通常通过套接字向网络发出请求或者应答网络请求。他是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元。它是网络通信过程中端点的抽象表示,包含进行网络通信必需的5中信息:连接使用的协议、本地主机的IP地址,本地进程的协议端口、远程主机的IP地址和远地进程的协议端口。

 

Socket有两种主要的操作方式:面向连接的和无连接的。

         面向连接:必须建立一个连接和一个呼叫,所有事情的到达顺序和出发顺序一致。

                   使用TCP协议,此时Socket必须在发送数据之前与目的地的Socket取得连接。

                   效率不高,但是安全。

         无连接:事情到达顺序和出发顺序不保证一致。

使用数据报协议,一个数据报是一个独立的单元,它包含了这次投递的所有信息。快速,高效,但安全性不高。

若数据的可靠性更重要的话推荐使用面向连接的操作。

Socket构造

Java.net中提供了两个类Socket和ServerSocket,分别用来表示双向连接的客户端和服务端。

部分构造方法如下:

Socket(InetAddress address,int port ,InetAddress localAddr ,int localPort)

Socket(InetAddress address, int port ,boolean stream)

Socket(SocketImpl impl)

ServerSocket(int port , int backlog, InetAddress bindAddr)

 

address、host、port分别表示双向连接中另一方的IP地址、主机名、端口号

stream指明Socket是流Socket还是数据报Socket

localAddr,bindAddr是本地机器的地址(ServerSocket的主机地址)

impl是Socket的父类,既可以创建ServerSocket,也可创建Socket

 

在选择端口时必须小心。每一个端口提供一种特定的服务,只有给出正确的端口,才能获取相应的服务。0~1023的端口号为系统所保留,例如http服务的端口号是80,telnet服务的端口号为21,ftp为23。所以我们在选择端口号时最好选择大于1023的数,防止发生冲突。在创建Socket时,如果发生错误,将产生IOException,在程序中必须对其进行处理。所以在创建Socket或ServerSocket时必须捕获或抛出异常。

ServerSocket

ServerSocketserver = newServerSocket(4321);

Socketsocket = server.accept();

如上,该server只能接受一个请求,接收后就退出,实际中的应用是用循环接收。

accept()是阻塞函数,即该方法被调用后将等待客户的请求,直到有一个客户启动并请求连接到相同的端口,然后accept()返回一个对应于客户的Socket。这时,客户方和服务方都建立的用于通信的Socket,接下来就是由各个Socket分别打开各自的输入、输出流。

 

 

输入流输出流

Socket提供了getInputStream()和getOutputStream()方法来得到输入输出流。然后再对输入流输出流进行读写操作,例如,对于服务器端,得到Socket对象后,调用getInputStream方法即可得到来自客户端的流,调用getOutStream方法可得到向客户端发送数据的流。对于客户端,调用getInputStream方法即可得到来自服务器的流,调用getOutStream方法可得到向服务器端发送数据的流。

 

 

关闭Socket和流

可调用Socket的close()方法进行关闭。在关闭前,应将与Socket相关的所有输入输出流关闭,正着打开,倒着关闭。

 

创建服务器的步骤:

1,  指定端口实例化一个ServerSocket

2,  调用ServerSocket的accept方法以在等待连接期间造成阻塞

3,  获取位于该底层Socket的流以进行读写操作

4,  将数据封装成流

5,  对Socket进行读写

6,  关闭打开的流

创建客户端的步骤:

1,  通过IP地址和端口实例化Socket,请求连接服务器

2,  获取Socket上的流以进行读写

3,  把流包装进BufferedReader/PrintWriter的实例

4,  对Socket进行读写

5,  关闭打开的流

 

当要监控多个客户端时,可使用类ExecutorService

其对象获取方法:Executors.newCachedThreadPool();

调用该对象的execute(Runnablecommand)即可,在未来某个时间执行给定的命令。该命令可能在新的线程、已入池的线程或者正调用的线程中执行,这由Executor