Java Socket 技术介绍

来源:互联网 发布:linux下压缩文件夹命令 编辑:程序博客网 时间:2024/05/16 12:02

在客户/服务器(C/S)通信模式中,客户端需要主动创建与服务器连接的 Socket(套接字),服务器端收到了客户端的连接请求,也会创建与客户连接的 Socket.

Socket可看做是通信连接两端的收发器,服务器与客户端都通过 Socket 来收发数据。

1. 构造Socket
* 1.1 使用无参数构造方法,设定等待建立连接的超时时间*

Socket socket = new Socket();SocketAddress remoteAddr = new InetSocketAddres("localhost",8000);//等待建立连接的超时时间为1分钟socket.connect(remoteAddr, 60000);

* 1.2 设定服务器的地址*

//第一个参数address 表示主机的IP地址Socket(InetAddress address, int port)//第一个参数host 表示主机的名字 Socket(String host, int port)//返回本地主机的IP地址InetAddress addr1 = InetAddress.getLocalHost()//返回代表 "222.34.5.7"的 IP地址InetAddress addr2 = InetAddress.getByName("222.34.5.7")

* 1.3 设定客户端的地址*

//参数localAddr 和 localPort 用来设置客户端的IP 地址和端口Socket(InetAddress address, int port, InetAddress localAddr, int localPort) throws IOExceptionSocket(String host, int port, InetAddress localAddr, int localPort) throws IOException

如果一个主机同时属于两个以上的网络, 它就可能拥有两个以上的IP 地址. 例如, 一个主机在Internet 网络中的IP 地址为 “222.67.1.34”, 在一个局域网中的IP 地址为 “112.5.4.3”. 假定这个主机上的客户程序希望和同一个局域网的一个服务器程序(地址为:”112.5.4.45: 8000”)通信, 客户端可按照如下方式构造Socket 对象:

InetAddress remoteAddr1 = InetAddress.getByName("112.5.4.45");InetAddress localAddr1 = InetAddress.getByName("112.5.4.3");//客户端使用端口2345Socket socket1 = new Socket(remoteAddr1, 8000, localAddr1, 2345);   

* 1.4 客户连接服务器时可能抛出的异常*
当Socket 的构造方法请求连接服务器时, 可能会抛出下面的异常.
UnKnownHostException: 如果无法识别主机的名字或IP 地址, 就会抛出这种异常.
ConnectException: 如果没有服务器进程监听指定的端口, 或者服务器进程拒绝连接, 就会抛出这种异常.
SocketTimeoutException: 如果等待连接超时, 就会抛出这种异常.
BindException: 如果无法把Socket 对象与指定的本地IP 地址或端口绑定, 就会抛出这种异常.
以上4中异常都是IOException的直接或间接子类
这里写图片描述

二. 获取Socket 的信息

在一个Socket 对象中同时包含了远程服务器的IP 地址和端口信息,以及客户本地的IP 地址和端口信息。此外,从Socket 对象中还可以获得输出流和输入流,分别用于向服务器发送数据,以及接收从服务器端发来的数据。以下方法用于获取Socket的有关信息

getInetAddress(): 获得远程服务器的IP 地址
getPort(): 获得远程服务器的端口
getLocalAddress(): 获得客户本地的IP 地址
getLocalPort(): 获得客户本地的端口
getInputStream(): 获得输入流. 如果Socket 还没有连接, 或者已经关闭, 或者已经通过 shutdownInput() 方法关闭输入流, 那么此方法会抛出IOException
getOutputStream(): 获得输出流, 如果Socket 还没有连接, 或者已经关闭, 或者已经通过 shutdownOutput() 方法关闭输出流, 那么此方法会抛出IOException

在HTTPClient 类中, 先创建了一个连接到该HTTP服务器的Socket对象, 然后发送符合HTTP 协议的请求, 接着接收从HTTP 服务器上发回的响应结果.

三. 关闭Socket

当客户与服务器的通信结束, 应该及时关闭Socket , 以释放Socket 占用的包括端口在内的各种资源. Socket 的 close() 方法负责关闭Socket. 当一个Socket对象被关闭, 就不能再通过它的输入流和输出流进行I/O操作, 否则会导致IOException.

为了确保关闭Socket 的操作总是被执行, 强烈建议把这个操作放在finally 代码块中:

Socket socket = null;try{  socket = new Socket(www.javathinker.org,80);  //执行接收和发送数据的操作  ..........  }catch(IOException e){  e.printStackTrace();}finally{  try{if(socket != null) socket.close();  }catch(IOException e){e.printStackTrace();}}

Socket 类提供了3 个状态测试方法.

isClosed(): 如果Socket已经连接到远程主机, 并且还没有关闭, 则返回true , 否则返回false
isConnected(): 如果Socket曾经连接到远程主机, 则返回true , 否则返回false
isBound(): 如果Socket已经与一个本地端口绑定, 则返回true , 否则返回false
如果要判断一个Socket 对象当前是否处于连接状态, 可采用以下方式:

boolean isConnected = socket.isConnected() && !socket.isClosed();

四. 设置Socket 的选项

Socket 有以下几个选项.

TCP_NODELAY: 表示立即发送数据
SO_RESUSEADDR: 表示是否允许重用Socket 所绑定的本地地址
SO_TIMEOUT: 表示接收数据时的等待超时数据
SO_LINGER: 表示当执行Socket 的 close()方法时, 是否立即关闭底层的Socket
SO_SNFBUF: 表示发送数据的缓冲区的大小
SO_RCVBUF: 表示接收数据的缓冲区的大小
SO_KEEPALIVE: 表示对于长时间处于空闲状态的Socket , 是否要自动把它关闭
OOBINLINE: 表示是否支持发送一个字节的TCP 紧急数据

下一篇: TCP协议与UDP协议的区别

原创粉丝点击