由于非CS科班出身,没有系统学过操作系统或微机原理,所以对计算机底层一直不是特别明白,所以在用到java网络编程的时候就头大,虽然知道socket怎么用,能搭建个B/S联通起来,但是socket到底是什么还是一概莫知。这篇随笔就当是让自己多了解一点这方面的知识吧。
首先,做一件事情最重要的是知道目的(why)。那么我们的目的就是让两台主机相互通信,只有让两台能通信,才能形成现在的互联网。
其次,做一件事情要知道怎么做(how)。想象一下两边放着两台电脑,让它们通信(也就是数据交换),那数据又不可能通过空气传播过去(当然我不了解手机和wifi是什么情况),所以肯定需要最最底层的东西,一条数据传输线,不管它现实中叫光纤也好电缆也好继电器也好,这就是OSI七层中最下一层--物理层。相当于我们两个人之间要交流,首先你得有喉咙舌头这些东西。
然后,要发送数据的主机开始物理地址寻址,数据帧的形成,数据的检验,这就是七层中的第二层--数据链路层。相当于两个人交流,其中准备要说话的那个组织下语言,并清了清嗓子。
然后,准备工作做好,下一步就是找到发送目标,也就是寻找合适的网间路由和交换节点,并从刚才的数据帧中提取出数据包包头,里面有目的站点的网络地址,这层里面的代表协议就是大名鼎鼎的IP协议,这就是OSI七层的第三层--网络层。相当于两个人交流,得一个找一个合适的地点,咖啡厅什么的。
然后,数据准备好,目标也有了,那就开始传输数据,这就没什么好解释的了,这层的代表协议就是我们后面要讲的TCP协议,这就是OSI七层中的第四次--传输层,这层是前三层和后上层的桥梁,非常重要。相当于两个人找到地方坐下来,其中一个人开始滔滔不绝的开讲了。
然后,后面就简单说一下,你说话的时候,别人不一定一直在那听啊,那么需要有东西保证两个是一直在会话的,这就是第五层--会话层
然后,说话的时候,两个人有相互表达不清楚的时候,或者想描绘个图什么的,这需要有东西保证将表达不清楚的解释清楚,将描绘的画下来给对方,这就是第六层--表示层
最后,将前面流程形成一套接口,做成应用,如果另外两个也想交流呢,就利用这套接口,改点东西,比如我在垃圾场见面啦,说的是郭嘉政治啦,他在汽车站见面啦,说的是天气真热什么的,再比如:HTTP、FTP、Telnet等,这就是最后一层--应用层
写到后面发现例子举的不太合适了,也是强行圆下去。ʅ(‾◡◝)
一般的麻瓜用的是第七层,比如点下网页的连接,它就发送了一个HTTP请求,当然他们看不到,请求报文是浏览器给他们写的,而我们程序员一般是从第四层的TCP开始用,怎么用呢,TCP有提供接口,就是Socket。它对TCP/IP协议做了抽象,也就有了create、connect、write、send、accept、close等等方法。
socket连接有个很重要的特性,就是三次握手,有必要写一下:
Client向Server发送一个Syn包(syn=j),并进入SYN_SEND状态(Syn是Synchronize Sequence Numbers同步序列号)
Server接收到确认Syn包(Syn=j+1),加上一个自己的Ack包(ack=k),然后一起发送回去,并进入SYN_RECV状态(Ack是acknowledge确认)
Client接收到两个包,并将Ack包(Ack=k+1)再次返回给Server,发送完毕后两边都进入Established状态。完成握手。
HTTP是TCP的一个非常重要的引用,也是互联网的基础,下次再说。至于TCP和UDP的区别我就不赘述了,而且我也没用过UDP。
下面给一个最简单的Socket连接示例。
1 public class DateServer { 2 public static void main(String[] args) throws IOException { 3 ServerSocket listener = new ServerSocket(9090); 4 try { 5 while (true) { 6 Socket socket = listener.accept(); 7 try { 8 PrintWriter out = 9 new PrintWriter(socket.getOutputStream(), true); 10 out.println(new Date().toString()); 11 } finally { 12 socket.close(); 13 } 14 } 15 } 16 finally { 17 listener.close(); 18 } 19 } 20 } 21 public class DateClient { 22 public static void main(String[] args) throws IOException { 23 String serverAddress = JOptionPane.showInputDialog( 24 "Enter IP Address of a machine that is\n" + 25 "running the date service on port 9090:"); 26 Socket s = new Socket(serverAddress, 9090); 27 BufferedReader input = 28 new BufferedReader(new InputStreamReader(s.getInputStream())); 29 String answer = input.readLine(); 30 JOptionPane.showMessageDialog(null, answer); 31 System.exit(0); 32 } 33 }
最后推荐一个基于java nio的Socket框架--Mina,非常强大,而且刚好这次的项目用上了,之后有时间就来写下mina好了。