Socket基础

1.OSI模型
      物理层 传输用的物理介质,以bit(0或1)流传输,Hub就在此层
      数据链路层 节点间传输,检测传输中的差错,以帧(二进制数据组成)为单位,Switch在该层
      网络层 IP协议在该层,选择不同的网络,以数据包(由帧组成)为单位,路由Router在该层
      传输层 传输数据,单位为报文,TCP、UDP协议就在传输层
      会话层 管理进程之间的会话过程
      表示层 数据的加密解密压缩与解压缩等
      应用层 http、FTP、telnet等协议在该层

2.TCP/IP模型
      应用层 ftp、telent、http,与OSI类似
      传输层 tcp、udp
      网络层 IP
      主机-物理层 以太网

3.URL
      统一资源定位器 Uniform Resource Locator
      网址属于URL,由协议://主机地址/路径
      通过ARP协议找到物理地址

4.TCP/UDP
      使用端口进行标识
      检测端口 start telent 127.0.0.1 9090
      查看端口 netstat -ano
      关闭端口 ntsd -c q -p PID

5.Socket基础
 设置连接超时,设为0则不会超时
       SocketAddress sa = new InetSocketAddress("localhost",8080);
       socket.connect(sa,1000);
 Socket地址可以使用字符串,或者InetAddress类来表示
 Socket对象包含了一些信息
       getInetAddress主机地址
       getPort 端口
       getLocalAddress 本地地址
       getLocalPort 本地端口
       getInputStream
       getOutputStream
 Socket关闭
       socket.close()
       isClosed();是否关闭
       isConnected();是否连接过
       isBound();是否已经绑定本地端口
       只关闭流,不关闭连接
             shutdownInput 关闭输入流
             shutdownOutput 关闭输出流
       同样可以检测是否已经关闭
             isInputShutdown
             isOutputShutdown
 Socket选项
       立即发送数据
             if(!socket.getTcpNoDelay()){
                   socket.setTcpNoDelay(true);
             }
       Socket关闭,暂未释放端口时,允许重用端口
              if(!socket.getResouceAddress()){
                   socket.setResouseAddress(true);
              }
       等待超时
             例如定义byte[1024]大小的空间,那么只有读取到byte数组中才会返回读取的字节数
             超时默认为0,即无限制
     if(socket.getTimeout == 0){socket.setTimeout(5000);}

View Code
 1 <span>// 服务端
 2 public static void main(String[] args) {
 3     // 创建Socket服务端
 4     try {
 5         ServerSocket server = new ServerSocket(8080);
 6         // 等待客户端连接
 7         Socket s = server.accept();
 8         // 获得Socket的输入流
 9         InputStream in = s.getInputStream();
10         // 字节数组输出流,数据会写入内存缓冲区
11         // 此过滤流好处是可以输出字节数组
12         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
13         byte[] buff = new byte[1024];
14         s.setSoTimeout(1000);
15         int len = -1;
16         try {
17             while((len=in.read(buff))!=-1){
18                 // 读取buff大小
19                 buffer.write(buff,0,len);
20             }
21         } catch (Exception e) {
22             System.out.println("超时");
23         }
24         // 超时时,仍可读取缓冲区中的数据
25         System.out.println(new String(buffer.toByteArray()));
26     } catch (Exception e) {
27         e.printStackTrace();
28     }
29 }</span>
View Code
 1 <span>// 客户端
 2 public static void main(String[] args) {
 3     try {
 4         // 创建Socket连接
 5         Socket s = new Socket("192.168.1.11",8080);
 6         // 取得Socket的输出流
 7         OutputStream out = s.getOutputStream();
 8         out.write("java socket".getBytes());
 9         out.write("hello world".getBytes());
10         Thread.sleep(2000);
11         //s.shutdownOutput();
12         s.close();
13     } catch (Exception e) {
14         e.printStackTrace();
15     } 
16 }</span>

      Socket关闭,底层是否立即关闭
             调用close方法时,底层socket不会立即关闭,直到数据发送完才会真正关闭
       linger徘徊的意思
             // 立即关闭,未发送的数据丢失
             socket.setSoLinger(true,0);
            // 如果数据发送完,则关闭,或延迟3000
             socket.setSoLinger(true,3000);

View Code
 1 <span>// 客户端
 2 public static void main(String[] args) {
 3     try {
 4         Socket s = new Socket("localhost",8080);
 5         // 当加入此方法时,客户端关闭,服务端则不能收到数据,并且会报超时的异常
 6         // 如果没有调用setSoLinger方法,即使客户端关闭,服务端仍然可以收到数据
 7         s.setSoLinger(true, 0);
 8         OutputStream out = s.getOutputStream();
 9         out.write("111111111111".getBytes());
10         System.out.println("关闭socket");
11         // 计算关闭socket所需的时间
12         long begin = System.currentTimeMillis();
13         s.close();
14         long end = System.currentTimeMillis();
15         System.out.println(end-begin);
16     } catch (Exception e) {
17         e.printStackTrace();
18     } 
19 }</span>

 

View Code
 1 <span>// 服务端
 2 public static void main(String[] args) {
 3     try {
 4         ServerSocket server = new ServerSocket(8080);
 5         Socket s = server.accept();
 6         // 休眠过后再读取数据
 7         try {
 8             Thread.sleep(6000);
 9         } catch (InterruptedException e) {
10         }
11         InputStream in = s.getInputStream();
12         ByteArrayOutputStream buffer = new ByteArrayOutputStream();
13         byte[] buff = new byte[1024];
14         int len = -1;
15         while((len=in.read(buff))!=-1){
16             buffer.write(buff,0,len);
17         }
18         System.out.println(new String(buffer.toByteArray()));
19     } catch (IOException e) {
20         e.printStackTrace();
21     }
22 }</span>

     接收数据缓冲区的大小
             socket.setReceiveBufferSize(1024);
             socket.getReceiveBufferSize();
     发送数据缓冲区大小
             socket.setSendBufferSize(1024);
             socket.getSendBufferSize();
      Socket处于空闲时是否关闭
      默认TCP不会监视连接是否有效,当设置为true时则超过一定时间会发送数据包检测
             if(!socket.getKeepAlive()){
                  socket.setKeepAlive(true);
             }
      发送紧急数据
             socket.setOOBInline(true);
      默认值为false,接收方不会对紧急数据作处理

 

 

posted @ 2013-04-24 13:37  轻云沉峰  阅读(351)  评论(0编辑  收藏  举报