客户端Socket

客户端Socket

1、什么是客户端Socket

客户端Socket相当于一个可以读写的字节流。

2、使用SocketSocket是两台主机之间的一个连接

a) 连接远程主机

b) 发送数据

c) 接收数据

d) 关闭连接

e) 绑定端口

f) 监听入站数据

g) 在绑定端口上接收来自远程机器(客户端)的连接。

Javasocket类(客户端和服务器都可以使用)提供了对应前4个操作的方法。后面3个操作仅服务器需要,即等待客户端的连接。Java程序通常采用以下方式使用客户端Socket

程序用构造函数创建一个新的Socket

Socket尝试连接远程服务器。

3、从服务器读取数据

创建一个连接:Socket socket = new Socket(url,port);

通过socket.getInputStream获取Inpustream对象,此时可以通过API读取服务器所送的数据。

对于大多数类似这样的网络程序中,重点工作通常是使用协议和理解协议,从而对socket所传输的数据进行解析。

4、向服务器写数据

同样是创建一个连接:Socket socket = new Socket(ip,port);

通过socket.getOutputStream获取Outpustream对象,此时可以通过API向服务器发送数据。

5、半关闭连接

close()方法会同时关闭socket的输入和输出。有时你可能希望只关闭连接的一般即输入或者输出。shutdownInput()shutdownOutput()方法只关闭连接的一半。但这并不会关闭socket。实际上它会调整与socket连接的流,使它认为已经到了流的末端。关闭输入之后再读取会返回-1,关闭输出之后再写入socket会抛出IOexception。注意,即使半关闭了连接,或将连接的两半都关闭,使用结束后仍需要关闭改socketshutdown方法只会影响socket流,并不释放与socket相关的资源和所占用的端口。可以用过isInputStream()isOutputStream()方法确定输入和输出流是否打开或者关闭。

6、构造和连接Socket

Socket(String host,int port);

Socket(InetAdress host, int port);

7、构造但不连接Socket

Socket();

Socket.connect(socketAdress)可以通过传入一个SocketAddress对象来穿件一个连接的socket;之所以有这个构造函数,是为了支持不同类型的socket,还需要用它设置一个socket选项,这个选项只能在socket连接之前改变。而SocketAdress主要用途是为暂时的socket连接信息(IP地址和端口)提供一个方便的存储,即使最初的socket已断开并被垃圾回收,这些信息也可以重新用来创建新的socket

8、代理服务器

Socket(proxy);

一般情况下,socket使用的代理服务器由socksProxyHostsocksProxyPort系统属性控制,这些属性应用于系统中的所有socket

下面代码使用位于ipsocks代理服务器来连接主机remoteip;

SocketAddress proxyAddress = new InetSocketAddress(ip, port);

Proxy proxy = new Proxy(Proxy.Type.SOCKS, proxyAddress ) ;

Socket s = new Socket(proxy);

SocketAddress remote = new InetSocketAddress(remoteip, port);

s.connect(remote);

9、获取Socket信息

getInetAddress();//获取远程地址

getPort();//获取远程地址端口

getLocalAddress();//获取本地地址

getLocalPort();//本地端口

由于socket是临时对象,一般来讲,socket的持续时间与他们表示的连接是一直的,所以没有理由把它们存储在散列表中或者进行比较。因此socket没有覆盖equals()或者hashCode()方法,这些方法的语义完全等同于Object宗相应方法。当且仅当两个socket对象是同一个对象时他们才相等。

10、设置Socket选项

a) TCP_NODEAY:设置TCP_NODEAYtrue会确保包会尽快地发送,而无论包大小。正常情况下,小数据包(一字节)在发送前会组合为更大的包。

b) SO_LINGER:该选项制定了socket关闭时如何处理尚未发送的数据。默认情况下,close()方法将立即返回,但系统仍会尝试发送剩余的数据。如果延迟时间设置为0,那么当socket关闭时,所有未发送的数据包都将被丢弃。如果该选项打开并且延迟时间设置为任意正整数,close()方法将会被阻塞(阻塞时间为指定秒数),等待发送数据和确认接收。当过去相应秒数时,所有剩余数据都不会被发送,也不会收到确认。

c) SO_TIMETOUT:设置超时时间

d) SO_RCVBUFSO_SNDBUF:设置接收和发送缓冲区

e) SO_KEEPALIVE:如果打开了SO_KEEPALIVE,客户端偶尔会通过一个空闲连接发送一个数据包(一般两小时一次),以确保服务器为崩溃。

f) OOBINLINE:TCP包括一个可以发送单字节之外“紧急数据”。这个数据会立即发送。此时接收方收到紧急数据时会得到通知,在处理其他已收到的数据之前可以选择先处理这个数据。

g) SO_REUSEADDR:一个socket关闭时,可能不会立即释放本地端口,尤其是当socket关闭时仍有一个打开的连接,就不会释放本地端口。有时会等待一小段时间,确保接收到所有要发送到这个端口的延迟数据包,socket关闭时这些数据包可能人在网络上传输。系统不会对接收到的延迟包做任何处理,只是希望确保这些数据不会意外地传入到绑定到统一端口的新进程。

如果使用随机端口,不会存在大问题,但是如果socket绑定到一个已知端口,就会阻塞所有其他socket同时使用这个端口。如果SO_REUSEADDR(默认关闭),就允许另一个socket绑定到这个端口,即使此时仍有可能存在前一个socket未接收的数据。

java中,可以通过以下两个方法来控制:

void setReuseAddress(boolean on);

boolean getReuseAddress();

要正常使用这些放法,setReuseAddress()必须在为这个端口绑定新端口之前调用。这意味着socket必须使用无参构造函数以非连接状态创建,然后调用setReuseAddresstrue,再使用connect()方法连接socket。之前连接的socket和重用的老地址的新socket都必须设置setReuseAddresstrue才能生效。

11Socket异常

BindException 如果在正在使用的端口上构造socketserverSocket对象,或者没有足够的权限使用这个端口,就会抛出该异常。

ConnectException 当远程主机拒绝,而拒绝的原有通常是主机忙或者没有进程监听该端口,就会抛出该异常。

NoRouteToHostException:连接超时

ProtocalException:网络接收数据违反TCP/IP规范。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值