客户端Socket概述与实例
来源:互联网 发布:淘宝买全民晒单 编辑:程序博客网 时间:2024/05/17 00:09
绝大部分知识与实例来自O’REILLY的《Java网络编程》(Java Network Programming,Fourth Edition,by Elliotte Rusty Harold(O’REILLY))。
Socket类简介
Socket又名套接字,由地址和端口号组成。它可以完成以下7个基本操作:
(1)连接远程机器;
(2)发送数据;
(3)接收数据;
(4)关闭连接;
(5)绑定端口;
(6)监听入站数据;
(7)在绑定端口上接收来自远程机器的连接。
Java的Socket类提供了对应前4个操作的方法,后面3个方法用于等待客户端的连接,仅服务器需要,由ServerSocket实现。
Socket类的使用大致可分为两个基本步骤:构造一个Socket对象并完成配置;利用Socket对象连接远程主机,并获取输入/输出流。
Socket对象的构建与简单使用
Socket的构造函数如下:
//构建一个空的Socket对象public Socket()//构建一个空的Socket对象,并设置代理服务器public Socket(Proxy proxy)//构建一个空的Socket对象,并设置加密机制public Socket(SocketImpl impl)//根据主机名和端口号构造Socket对象public Socket(String host, int port) throws UnknownHostException, IOException//根据InetAddress对象和端口号构造Socket对象public Socket(InetAddress address, int port) throws IOException//允许设置在哪个本地接口连接public Socket(String host, int port, InetAddress localAddr,int localPort) throws IOException
各个构造器的参数见注释。需要注意的是,前三个构造器在创建对象时不会打开与远程主机的连接(因为没有提供地址和端口号),而后面的构造器则会。另外,由于Socket实现了Closeable,因此最好利用Java 7的try-with-resources实现自动关闭。
创建Socket对象并建立连接后,就可以调用Socket的getInputStream()获取来自服务器的输入了。
实例1:Daytime协议客户端
public static void showDayTime(){ String hostName = "time.nist.gov"; try(Socket socket = new Socket(hostName, 13)){ socket.setSoTimeout(15 * 1000); StringBuilder builder = new StringBuilder(); try(InputStreamReader reader = new InputStreamReader(socket.getInputStream(),"ASCII")){ for(int c = reader.read() ; c != -1 ;c = reader.read()){ builder.append((char)c); } } System.out.println(builder.toString()); } catch (UnknownHostException e) { System.out.println("Unknown Host."); } catch (IOException e) { e.printStackTrace(); }}public static void main(String[] args){ showDayTime();}输出:58007 17-09-11 02:33:20 50 0 0 938.2 UTC(NIST) *
向服务器写入数据
如果需要向服务器写入数据,只需要通过Socket的getOutputStream()方法获得一个输出流,然后向这个输出流输出数据即可。输出结束后必须手动调用输出流的flush()方法确保发送。
关闭Socket
close()方法同时关闭输入和输出,如果只想关闭一半,可以使用shutdownInput()和shutdownOutput()方法。
获取Socket对象的信息
Socket类提供了一些方法,用于获取某个Socket对象的信息:
//获取远程主机地址public InetAddress getInetAddress()//获取远程主机端口public int getPort()//获取本地端口public int getLocalPort()//连接是否处于关闭状态public boolean isClosed()//连接是否成功打开过public boolean isConnected()//Socket是否成功绑定到本地系统的出站端口public boolean isBound()public String toString()输出样例:Socket[addr=www.baidu.com/183.232.231.172,port=80,localport=10307]
设置Socket选项
Socket选项指定了Java Socket依赖的原生socket如何发送和接收数据。有以下选项可用:
(1)TCP_NODELAY
public void setTcpNoDelay(boolean on) throws SocketExceptionpublic boolean getTcpNoDelay() throws SocketException
正常状况下,为了提升效率,小数据包发送前会组合成大包再发送。设置TCP_NODELAY为true可确保包会尽可能快地发送,无论包的大小。简单来讲,setTcpNoDelay(true)会关闭socket的缓冲功能。
(2)SO_LINGER
public void setSoLinger(boolean on, int linger) throws SocketExceptionpublic int getSoLinger() throws SocketException
SO_LINGER指定了Socket关闭时如何处理尚未发送的数据报。默认情况下,close()方法会立即返回,但系统仍会尝试发送剩余的数据。如果延迟时间设置为0,那么当Socket关闭时,所有未发送的数据报都将被丢弃。如果SO_LINGER设置为打开并设置一个任意正数的延迟时间,close()方法会阻塞,等待发送数据和接收确认。
当这个选项被禁用时,getSoLinger()方法返回-1。
(3)SO_TIMEOUT
public synchronized void setSoTimeout(int timeout) throws SocketExceptionpublic synchronized int getSoTimeout() throws SocketException
正常情况下,尝试从Socket读取数据时,read()方法会阻塞尽可能长的时间来得到足够的字节。设置SO_TIMEOUT可以确保一次调用阻塞的时间不超过某个固定的毫秒数。如果超时,会抛出一个InterruptedIOException,但不会中断socket的连接。
(4)SO_RCVBUF与SO_SNDBUF
public synchronized void setReceiveBufferSize(int size) throws SocketExceptionpublic synchronized int getReceiveBufferSize() throws SocketExceptionpublic synchronized void setSendBufferSize(int size) throws SocketExceptionpublic synchronized int getSendBufferSize() throws SocketException
用于设置接收缓冲区大小与发送缓冲区大小,单位为字节。一般来说,如果不能充分利用带宽,应当增大缓冲区;若网络拥塞严重,应当减小缓冲区。
(5)SO_KEEPALIVE
public void setKeepAlive(boolean on) throws SocketExceptionpublic boolean getKeepAlive() throws SocketException
如果打开了SO_KEEPALIVE,客户端会偶尔通过一个空闲连接发送一个数据包,以确保服务器未崩溃。如果服务器未能响应,客户端会继续尝试一段时间(一般12分钟),直到接收到响应为止,否则连接将被关闭。
(6)SO_REUSEADDR
public void setReuseAddress(boolean on) throws SocketExceptionpublic boolean getReuseAddress() throws SocketException
设置是否允许多个Socket绑定到同一个端口,默认为false(不允许)。这个设置想要生效,首先它要在绑定端口之前调用,也就是要先用非连接的几种构造器创建Socket对象,然后设置该属性为true,最后再调用connect()完成连接。还有一点,新老Socket必须同时设置该属性为true,否则该设置也无法起效。
以上几个属性的setter如果抛出SocketException,一般指底层socket不支持该属性。
- 客户端Socket概述与实例
- 服务器Socket概述与实例
- Socket服务器与客户端双向通信实例
- Java Socket服务器与客户端实例
- windows socket 服务器与客户端开发实例
- Socket客户端与服务端通讯实例
- android客户端与服务器socket通信实例
- android socket 客户端实例
- Java socket客户端与服务端同步通信实例
- Android客户端与PC服务器通过socket进行交互实例
- php的socket服务端监听与客户端访问实例脚本
- Android客户端与PC服务器通过socket进行交互实例
- Android客户端与PC服务器通过socket进行交互实例
- Android客户端与PC服务器通过socket进行交互实例
- 用C++编写的SOCKET服务端与客户端代码实例
- Socket客户端与服务端
- LSA概述与实例
- C#和PHP Socket通信实例代码(服务器与客户端通信)
- ubuntu16.04虚拟机桥接模式无法联网问题解决
- ubuntu 常见的错误 Could not get lock /var/lib/dpkg/lock
- 第二周项目1函数参数传递的三种方式
- shiro 学习
- PHP面向对象之简单工厂模式
- 客户端Socket概述与实例
- 分页池和非分页池的基本概念
- 通过mysqlbinlog --skip-gtids恢复后再备份可能造成的坑
- argc argv参数
- Linux服务器I/O
- 表单验证
- Test2 打印出所有的"水仙花数"
- crosstool-ng详解
- Maven使用—拷贝Maven依赖jar包到指定目录