客户端套接字
数据是以有限到小的分组的形式通过Internet传输的; 一个分组是一个数据报,包括首部和负载;
套接字的出现使得我们不必关心这个传输过程中数据报如何分割有效负载为信息,生成首部,解析到来的
的信息,留意收到了什么包没收到什么包等细节工作;我们只需要把网络看成一个流,就象对文件一样
对这个流进行操作就行了;
套接字非常简单,然而,与不同服务器通信的协议使工作变得非常复杂;
Socket类
可以说这个类是网络编程中的祖先,URL,URLConnection,Applet,JEditorPane都是以调用这个类的
方法结束的;
构造函数:
public Socket(String host,int port) throws UnknownHostException,IOException
注意host仅仅是主机名而不是一个URL;
注意这个构造方法不只是象其他的构造方法创建了Socket对象,它还连接套接字到远程主机的端口;
所以我们可以用这个类还测试一个主机上有哪些服务;
//InetAddress和String标识的主机是一个档次的,不象URL那么丰富多彩;
Socket(InetAddress address, int port, InetAddress localAddr, int localPort)
这个构造的说明:
我们用客户端的Socket尝试连接远程主机,所以我们指定了远程主机名和端口,就象前面
的构造函数和这个构造函数里的前两个参数所描述的那样;但是我们在连接别人的时候
自己的机器也被占用了某个端口,一般来说,如果没有指定,则系统会随机找一个端口,就象前面
没有localPort参数的构造函数一样;在这个构造里,如果你指定localPort是0,那么也可以
达到随机占用本机端口的效果;也许你很奇怪,localPort也许有必要特意指定一下,
但是localAddr还指定什么,不就是我的机器的名字吗?但是,有的机器不止一个名字;
Socket()构造只是创建对象,但是不连接;
getInetAddress(),getPort()得到的信息都是远程主机的而不是自己的;
其实想想也对,哪个白吃要知道自己的主机名和端口呢?
其实对应着有getLocalAddress(),getLocalPort();
如果你建立了一个对远程主机的套接字的输入流,不要以为你可以从这个输入流直接读到东西了;
你可以读,但是不是每个服务都会自动给你发数据的,当你连接它的时候;
我们用URLConnection请求一个URL,或者用浏览器请求一个URL,都会给我们马上返回数据,
那是因为无论是浏览器还是URLConnection其实都偷偷地在你请求一个URL的时候就给服务器
发送了请求数据,服务器做为响应才给你发的数据,看起来好像是服务器很贱一样,主动
给你发数据。所以一般情况下你必须主动给服务器发数据请求,它才会在你的套接字输入流里
放点东西供你读;
**************
*****关闭套接字:
其实当两个数据流之一被关闭,程序结束或者它作为无用数据收集时,套接字确实是自动关闭的;
但是,假设系统将关闭套接字是个不好的做法,特别是针对可能运行无限长时间的程序来说更是如此;
套接字关闭后:
getXXX仍然可以得到真确的数据;
getInputStream(),getOutputStream()也会正常工作,但是试图读写数据时就会异常;
半关闭:
shutdownInput();
shutdownOutput();
注意,两个半关闭方法合起来并不能达到close()的效果;
半关闭方法只上关闭数据流,其他资源还是没有关闭;
所以必须再调用close()方法才是正道;
************
***Object方法
Socket对象的生命周期和它对主机的连接主机一般是一样长;
***********
***设置套接字选项
setTcpNoDelay(boolean on) :我们知道Tcp的规则就是在发送一个包之前,本地机器会等待远程主机
对上一次发送的包的确认信息到来;这个方法就可以关闭套接字的缓存,
以至这要包准备好了就发;
setSoLinger(boolean on, int seconds) :close()方法被调用之后,on决定了对尚未发出去的数据报
是置之不理还是继续发送;seconds决定了延迟的时间;一般用默认!
setSoTimeout(int milliseconds):0是默认值,表示无限制超时连接;如果本次连接超时会抛出异常,
但是套接字还可以用,你可以重新read();
setReceiverBufferSize(int size):SO_RCVBUF
setSendBufferSize(int size) : SO_SNDBUF
setKeepAlive(boolean on) :如果被打开,客户机会隔段时间给服务器发包以确认服务器是否崩溃;
***********
***套接字的异常
java.net.SocketException 是IOException的一个子类;
SocketException有三个有用的子类:
BindException;
ConnectException;
NoRouteToHostException;