NIO与Socket笔记 :实现Socket 通信[ 一 ]

基于TCP的Socket通信

 

TCP 是一种 流协议,以流为单位进行数据传输 。

 

什么是长连接?

长连接可以实现当服务端与客户端连接成功后连续地传输数据,在这 个过程中,连接保持开启的状态,数据传输完毕后连接不关闭 。

长连接是指建立 Socket 连 接后,无论是否使用这个连接,该连接都保持连接的状态 。

什么是短连接?

短连接是当服务端与客户端连接成功后开始传输数据,数据传输完毕 后则连接立即关闭,如果还想再次传输数据,

则需要再创建新的连接进行数据传输 。

什么是连接?

在 TCP/IP 中, 连接可以认为是服务端与客户端确认彼 此都存在的过程 。

 

由于 UDP 是无连接协议,也就是服务端与客户端 没有确认彼此都存在的握手过程,因此在 UDP 里面不存在长连接与短连接的概念 。

 

长连接的优缺点
优点:   除了第一次之外,客户端不需要每次传输数据时都先与服务端进行握手,这样就减少了握手确认的时间,直接传输数据,提高程序运行效率 。 
缺点:   在服务端保存多个 Socket对象,大量占用服务器资源。

短连接的优缺点
优点 : 在服务端不需要保存多个 Socket对象,降低内存占用率 。
缺点 : 每次传输数据前都要重新创建连接,也就是每次都要进行 3 次握手,增加处理的时间 。

 

验证 ServerSocket 类的 accept()方法具有阻塞特性

ServerSocket类的作用是创建 Socket (套接字)的服务端,而 Socket类的作用是创建 Socket 的客户端 。 在代码层面使用的方式就是使用 Socket类去连接 ServerSocket类,也就是客户端要主动连接服务端 。

 

ServerSocket 类中的 public Socket accept()方法的作用是侦听并接受此套接字的连接 。

此方法在连接传人之前一直阻塞。

有客户端连接到服务 端时就不再出现阻塞 了,服务端的程序会继续运行 。

 

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class CreateWebServer {

    public static void main(String[] args) throws Exception {
        ServerSocket serverSocket = new ServerSocket(7777) ;
        Socket socket= serverSocket.accept() ;
        InputStream inputStream = socket.getInputStream() ;
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream); 
        BufferedReader bufferedReader = new BufferedReader(inputStreamReader) ;
        String getString = "";
        while (!"".equals(getString = bufferedReader.readLine())) {
            System.out.println(getString);
            OutputStream outputStream = socket.getOutputStream();
            outputStream.write("HTTP/1.1 200 OK\r\n\r\n".getBytes());
            outputStream.write("<html><body><a href='http://www.baidu.com'> i am baidu.com welcome you ! </a> </body></html> ".getBytes());
            outputStream.flush();
            inputStream.close();
            outputStream.close();
            socket.close ();
            serverSocket.close();

        }
    }

}

在 IE 浏览器地址栏中输入以下网址 :  http://127.0.0.1:7777/

 

 

验证 Socket 中 lnputStream 类的 read()方法也具有阻塞特性

除了 ServerSocket类 中的 accept()方法具 有阻塞特性外, InputStream类中的 read()方法 也同样具有阻塞特性 。

read()方法阻塞 的原因是客户端并未发送数据到服务端,

服务端一 直在尝试读取从客户端传递过来的数据,

因为客户端从未发送数据给服务端,所以服务端一直在阻塞。

 

客户端向服务端传递字符串

 

package com.nio.socket;

import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws Exception {
        char [] charArray = new char [3] ;
        ServerSocket serverSocket = new ServerSocket(7777) ;

        System.out.println(" accept begin "+ System.currentTimeMillis() ) ;
        Socket socket = serverSocket . accept();
        System.out.println("accept end " + System.currentTimeMillis()) ;

        InputStream inputStream = socket.getInputStream();
        InputStreamReader inputStreamReader = new InputStreamReader(inputStream);
        System. out. println ("read begin"  + System.currentTimeMillis());
        int readLength = inputStreamReader . read(charArray) ;
        while (readLength != -1) {
            String newString = new String(charArray, 0, readLength);
            System.out.println(newString);
            readLength = inputStreamReader.read(charArray);
            System.out.println("read end " + System.currentTimeMillis());

            inputStreamReader.close();
            inputStream.close();
            socket.close();
            serverSocket.close();

        }
    }
}

 

package com.nio.socket;

import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;

public class Client {

    public static void main(String[] args) throws Exception {
        System.out.println ("socket begin "+ System.currentTimeMillis()) ;

        Socket socket = new Socket("localhost", 7777) ;
        System.out.println( "socket end " + System.currentTimeMillis()); ;
        Thread.sleep(3000);
        OutputStream outputStream = socket .getOutputStream() ;
        outputStream.write (" 我是外星人 " . getBytes()) ;
        outputStream.close() ;
        socket .close();
    }
}

 

服务端向客户端传递字符串

 

package com.nio.socket.test41;


import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws Exception {

        ServerSocket serverSocket = new ServerSocket(7777) ;

        System.out.println(" accept begin "+ System.currentTimeMillis() ) ;
        Socket socket = serverSocket . accept();
        System.out.println("accept end " + System.currentTimeMillis()) ;


        OutputStream outputStream = socket.getOutputStream() ;
        outputStream.write ( " 我来自 server 端 ! ".getBytes() );

        outputStream.close();
        socket .close();
        serverSocket .close();


    }
}

 

package com.nio.socket.test41;

import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.net.Socket;

public class Client {

    public static void main(String[] args) throws Exception {
        System.out.println ("socket begin "+ System.currentTimeMillis()) ;

        Socket socket = new Socket("localhost", 7777) ;
        System.out.println( "socket end " + System.currentTimeMillis());


        char [] charBuffer = new char [3];
        InputStream inputStream = socket.getInputStream();

        InputStreamReader inputStreamReader = new InputStreamReader(inputStream) ;

        System.out.println("serverB begin "+ System.currentTimeMillis()) ;
        int readLength = inputStreamReader . read(charBuffer) ;
        System.out.println("serverB begin " + System.currentTimeMillis());
        while (readLength != 1) {
            System.out.print(new String(charBuffer, 0, readLength));
            readLength = inputStreamReader.read(charBuffer);
        }

        System.out.println(); ;

        inputStream.close() ;
        socket .close();
    }
}

 

 

允许多次调用 write()方法进行写入操作

write()方法允许多次被调用 ,每执行一次就代表传递一次数据。

 

实现服务端与客户端多次的往来通信

 

package com.nio.socket.test5;

import java.io.*;
import java.net.ServerSocket;
import java.net.Socket;

public class Server {
    public static void main(String[] args) throws Exception {
        char [] charArray = new char [3] ;
        ServerSocket serverSocket = new ServerSocket(7777) ;

        System.out.println(" accept begin "+ System.currentTimeMillis() ) ;
        Socket socket = serverSocket . accept();
        System.out.println("accept end " + System.currentTimeMillis()) ;


        //输入开始
        InputStream inputStream = socket .getInputStream ( ) ;
        ObjectInputStream objectInputStream = new ObjectInputStream (inputStream) ;
        int byteLength = objectInputStream.readInt();
        byte [] byteArray = new byte [byteLength] ;
        objectInputStream . readFully(byteArray) ;
        String newString = new String (byteArray);
        System .out. println(newString );
        //输入结束

        //输出开始
        OutputStream outputStream = socket .getOutputStream() ;
        String strA = "客户端你好 A\n" ;
        String strB = "客户端你好 B\n";
        String strC = "客户端你好 C\n";

        int allStrByteLength = (strA + strB + strC) .getBytes().length ;


        ObjectOutputStream objectOutputStream = new ObjectOutputStream(outputStream) ;
        objectOutputStream.write (allStrByteLength);
        objectOutputStream.flush() ;
        objectOutputStream.write(strA . getBytes());
        objectOutputStream.write(strB.getBytes()) ;
        objectOutputStream.write(strC .getBytes()) ;
        objectOutputStream .flush() ;
        //输出结束

        //输入开始
        byteLength = objectInputStream.readInt() ;
        byteArray = new byte [byteLength] ;
        objectInputStream .readFully(byteArray) ;
        newString = new String(byteArray) ;
        System.out.println(newString) ;
        // 输入结束

        //输出开始
        strA ="客户端你好 D\n" ;
        strB= "客户端你好E\n";
        strC = " 客户端你好 F\n";

        allStrByteLength = (strA + strB + strC) .getBytes() . length ;

        objectOutputStream .writeInt (allStrByteLength);
        objectOutputStream . flush () ;
        objectOutputStream .write(strA .getBytes()) ;
        objectOutputStream .write(strB .getBytes()) ;
        objectOutputStream .write(strC .getBytes()) ;
        objectOutputStream.flush() ;
        //输出结束
        inputStream . close () ;
        socket.close();
        serverSocket.close();


}
}

 

 

package com.nio.socket.test5;

import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.net.Socket;

public class Client {

    public static void main(String[] args) throws Exception {
        System.out.println ("socket begin "+ System.currentTimeMillis()) ;

        Socket socket = new Socket("localhost", 7777) ;
        System.out.println( "socket end " + System.currentTimeMillis());

        OutputStream outputStream = socket .getOutputStream();
        InputStream inputStream = socket.getInputStream() ;

        // 输出开始
        ObjectOutputStream objectOutputStream = new ObjectOutputStream (outputStream) ; 
        String strA = "服务端你好A\n";
        String strB = " 服务端你好 B\n";
        String strC = "服务端你好 C\n";
        
        int allStrByteLength = (strA + strB + strC) . getBytes() .length ; 
        objectOutputStream.write(allStrByteLength) ; 
        objectOutputStream.flush() ;
        objectOutputStream .write(strA.getBytes()) ; 
        objectOutputStream.write(strB.getBytes()) ;
        objectOutputStream .write(strC.getBytes()) ;
        objectOutputStream.flush() ;
        //输出结束

        // 输入开始
        ObjectInputStream objectInputStream = new ObjectInputStream(inputStream);
        int byteLength = objectInputStream.readInt() ;
        byte [] byteArray = new byte [byteLength] ;
        objectInputStream .readFully(byteArray);
        String newString = new String(byteArray) ;
        System .out.println(newString);
        //输入结束

        //输出开始
        strA = "服务端你好D\n";
        strB ="服务端你好 E\n";
        strC = "服务端你好F\n";
        allStrByteLength = (strA + strB + strC) .getBytes() . length ;
        objectOutputStream .writeInt(allStrByteLength) ;
        objectOutputStream.flush();
        objectOutputStream .write(strA.getBytes()) ;
        objectOutputStream .write(strB.getBytes()) ;
        objectOutputStream.write(strC.getBytes()) ;
        objectOutputStream.flush () ;
        //输出结束


        //输入开始
        byteLength = objectInputStream.readInt();
        byteArray = new byte[byteLength] ;
        objectInputStream.readFully(byteArray) ;
        newString = new String(byteArray) ;
        System . out .println(newString) ;
        //输入结束



        objectOutputStream.close() ;
        outputStream.close() ;
        socket .close();
    }
}

 

调用 Stream 的 close()方法造成 Socket 关闭

 

 

/**
 * Closes the stream.
 */
private boolean closing = false;
public void close() throws IOException {
    // Prevent recursion. See BugId 4484411
    if (closing)
        return;
    closing = true;
    if (socket != null) {
        if (!socket.isClosed())
            socket.close();
    } else
        impl.close();
    closing = false;
}

 

使用Socket传递PNG图片文件

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

 

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值