Java网络编程笔记——Socket用法详解

Socket笔记——Socket用法详解

       在客户/服务器通信模式中,客户端需要主动创建与服务器连接的Socket,服务器端接收到了客户端的连接请求,也会创建与客户点的连接Socket。Socket可以看作是通信连接两端的收发器,服务器与客户端都通过Socket来收发数据。

构造Socket

Socket() //通过系统默认类型的 SocketImpl 创建未连接套接字 

Socket(InetAddress address, int port)//创建一个流套接字并将其连接到指定 IP 地址的指定端口号。 

Socket(InetAddress address, int port, InetAddress localAddr, int localPort) //创建一个套接字并将其连接到指定远程地址上的指定远程端口。 

 

设置等待建立连接的超时时间

       当客户端的Socket构造方法请求与服务器连接时,可能需要等待一段时间。默认情况下,Socket构造方法会一直等待下去,知道连接成功,或者出现异常。Socket构造方法请求连接时,受底层网络的传输速度影响,可能会处于长时间的等待状态。

如果希望限定等待连接的时间,需要设置建立连接的超时时间,此时需要一个不带啊承诺书的构造方法:

Socket socke = new Socket();

SocketAddress remoteAddr = new InetSocketAddress("localhost":8000);

socket.connect(remoteAddr,60000);//等待建立连接超时时间为1分钟

如果程序在1分钟内成功连接,则connect()方法顺利返回;如果在1分钟内出现某种异常,则抛出该异常;如果超过1分钟,既没有连接成功,也没有出现其他异常,则会抛出SocketTimeoutException。Socket类的connect(SocketAddress endpoint,int timeout)方法负责连接服务器,参数endpoint指定服务器地址,参数timeout设定超市时间,以毫秒为单位,如果参数timeout设为0,表示永远不会超时

 

设定服务器地址:

       Socket除了一个不带参数的构造方法,其它的构造方法都需在参数中设定服务器的地址,包括服务器的IP地址或者主机名,以及端口:

Socket(InetAddress address,int port)//第一个参数address表示主机的IP地址

Socket(String host,int port)//第一个参数host代表主机的名字

InetAddress类表示服务器的IP地址,InetAddress类提供了一系列静态方法,用于构造自身实例,例如:

//返回本地主机IP地址

InetAddress addrl = InetAddress.getLocalHost();

//返回“222.23.2.2”的IP地址

InetAddress addr2 = InetAddress.getByName("222.23.2.2);

//返回域名为www.googel.com的ip地址

InetAddress addr3 = InetAddress.getByName("www.googel.com");

 

设定客户端的地址

       在一个Socket对象中,既保包含了远程服务器的IP地址和端口信息,也柏涵了本地客户端的IP地址和端口信息。默认情况下客户端的IP地址来自于客户端程序所在的主机。客户端的端口地址则来自于操作系统的随机分配。

Socket类还有两个构造方法允许显示地设置客户端的IP地址和端口

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

          创建一个套接字并将其连接到指定远程地址上的指定远程端口。

如果一个主机同时属于两个以上的网络,它就可能拥有连个以上的IP地址。

 

获得Socket信息:

getInetAddress():获得远程服务器的IP地址

getPort():获得远程服务器的端口

getLocalAddress():获得客户班底的IP地址

getInputStream():获得输入流。如果Socket还没有连接,或者已近关闭,或者已经通过shutdownInput()方法关闭输入刘,那么此方法会抛出IOException。

getOutputStream():获得输出流,如果Socket还没有连接,或者让已经关闭,或者已近通过shutDown()方法关闭输出流,那么此方法会抛出IOException

关闭Socket:

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

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

 

设置Socket选项:

SO_RESUSEADDR:表示是否允许重用Socket所绑定的本地地址

SO_TIMEOUT:表示接收数据时的等待超时时间

SO_LINGER:表示当执行Socket的close方法时,是否立即关闭底层的Socket

SO_SNFBUF:表示发送数据的缓存区大小

SO_RCVBUF:表示接受数据的缓冲区大小

SO_KEEPALIVE:表示对于长时间处于空闲状态的Socket,是否要自动把它关闭。

 

TCP_NODELAY:表示立即发送数据

设置选项:public void setTcpNoDelay(boolean on)throws SocketException

读取选项: public boolean getTcpNoDelay()throws SocketException

默认情况下,发送数据采用Negale算法,Negale算法发送数据不会立即发送,而是先放在缓冲区内,等缓存区满了以后再发出去。发送完一批数据后,会等待接受放对这批数据的回应,然后才发送下一批数据。Negale适用于发送放需要发送大批量数据,并且接收方会及时做出回应的场合,这种算法通过减少传输数据的次数来提高通信效率。

不过对于GUI程序,如网络游戏程序等需要实时发送数据到服务器上,由于Negale算法采用缓冲,大大降低了实时的响应速度,导致客户程序运行很慢。

TCP_NODELAY默认值为false,表示采用Negale算法。如果调用setTcpNoDelay(true),就会关闭Sokcet的缓冲,确保数据即使发送

SO_RESUSEADDR选项

设置该选项:public void setResuseAddress(boolean on)throws SocketException

读取该选项:public void getResusAddress(boolean on)throws SocketExcpetion

当接收放通过Socket的close()方法关闭Socket时候,如果网络上还有发送到这个Socket的数据,那么底层的Socket不会释放本地端口,而是等待一段时间,确保接收到了网络上发送来的延迟数据,然后再释放端口。Socket接收到的延迟数据后,不会对这些数据做任何树立,Socket接收延迟数据的目的是,确保这些数据不会被其他碰巧绑定到同样端口的新进程接收到。

为了确保一个进程关闭Socket后,即使它还没有释放端口,同一个主机上的其他进程还可以立刻重用该端口,可以调用Socket的setResuseAddress(true)方法:

if(!socket.getResuseAddress())socket.setResuseAddress(true):

值得注意的是socket.setResuseAddress(true)方法必须在Socket还没绑定到一个本地端口之前调用,否则执行socket.getResuseAddress(true)方法无效。

SO_TIMEOUT选项

设置该选项:public void setSoTimeout(int milliseconds)throws SocketException

读取该选项: public int getSoTimeOut()throws SocketException

当通过Socket的输入流读取数据时,如果还没有数据就会等待,例如在一下代码中,in.read(buff)方法从输入流中入去1024个字节:

byte[] buff = new byte[1024];

InputStream in=socket.getInputStream();

in.read(buff);

如果输入流中没有数据,in.read(buff)就会等待发送方发送数据,知道满足一下情况才结束等待:

1)输入流中有1024个字节,read()方法把这些字节读入到buff中,再返回读取的字节数

2)当已近快接近输入流的末尾,距离末尾还有小于1024字节,read()方法会把这些字节读取到buff中,再返回读取的字节数

3)已近读到输入流的末尾,返回-1

4)连接已近断开,抛出IOException

5)如果通过Socket的setSoTimeout方法设置了等待超时时间,那么超过这一时间后抛出SocketTimeoutException

Socket类的SO_TIMEOUT选项用于设定接收数据的等待超时时间,单位为毫秒,它的默认值为0,表示会无线等待,永远不会超时

SO_LINGER选项

设置该选项:public void setSoLinger(boolean on,int seconds)throws SocketException

读取该选项:public void getSoLinger()throws SocketException

SO_LINGER选项用来控制Socket关闭时的行为,默认情况下,执行Socket的close()方法,该方法会立刻返回,但底层的Socket实际上并不会立即关闭,它会延迟一段时间,知道发送完所有剩余的数据,才会真正关闭Socket,断开连接

如果执行以下方法:socket.setSoLinger(true,0):

那么执行Socket的close()方法,该方法也会立即返回,但底层的Socket也会立刻关闭,所有为发送完的剩余数据被丢弃

SO_KEEPALIVE选项

设置该选项:public void setKeepAlive(boolean on)throws SocketException

读取该选项:public void getKeepAlive()throws SocketException

当SO_KEEPALIVE选项为true时,表示底层的TCP实现会见识该连接是否有效。如果连接处于空闲状态超过2小时,本地的TCP实现会发送一个数据包给远程的Socket。如果远程Socket没有发回响应,TCP实现就会持续尝试11分钟,知道接收到响应为止。如果12分钟内未收到响应,TCP实现会自动关闭本地Socket,端口连接,在不同的网络平台上,TCP实现尝试与远程Socket对话的时限会有所差别

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值