Java NIO - ช่อง ServerSocket

แชนเนลซ็อกเก็ตเซิร์ฟเวอร์ Java NIO เป็นแชนเนลประเภทที่เลือกได้อีกครั้งซึ่งใช้สำหรับซ็อกเก็ตการเชื่อมต่อกระแสข้อมูลที่มุ่งเน้นการสตรีมแชนเนลซ็อกเก็ตเซิร์ฟเวอร์สามารถสร้างได้โดยการเรียกใช้สแตติก open() วิธีการจัดเตรียมซ็อกเก็ตที่มีอยู่แล้วใด ๆ ไม่มีอยู่แล้วช่องเสียบเซิร์ฟเวอร์ถูกสร้างขึ้นโดยการเรียกใช้วิธีการเปิด แต่ยังไม่ถูกผูกไว้เพื่อผูกช่องซ็อกเก็ต bind() จะเรียกวิธีการ

จุดหนึ่งที่จะกล่าวถึงในที่นี้คือหากช่องสัญญาณไม่ถูกผูกไว้และพยายามดำเนินการ I / O ใด ๆ แล้ว NotYetBoundException จะถูกโยนทิ้งโดยแชนเนลนี้ดังนั้นเราต้องแน่ใจว่าช่องถูกล้อมรอบก่อนที่จะดำเนินการ IO

การเชื่อมต่อขาเข้าสำหรับช่องซ็อกเก็ตเซิร์ฟเวอร์จะรับฟังโดยการเรียกใช้เมธอด ServerSocketChannel.accept () เมื่อวิธีการยอมรับ () ส่งคืนจะส่งคืน SocketChannel พร้อมการเชื่อมต่อขาเข้า ดังนั้นวิธีการยอมรับ () จะบล็อกจนกว่าจะมีการเชื่อมต่อขาเข้าหากช่องสัญญาณอยู่ในโหมดไม่ปิดกั้นวิธีการยอมรับจะส่งคืนค่าว่างทันทีหากไม่มีการเชื่อมต่อที่รอดำเนินการ มิฉะนั้นจะบล็อกอย่างไม่มีกำหนดจนกว่าจะมีการเชื่อมต่อใหม่หรือเกิดข้อผิดพลาด I / O

ซ็อกเก็ตของช่องใหม่เริ่มหลุด จะต้องถูกผูกไว้กับแอดเดรสเฉพาะผ่านวิธีการผูกของซ็อกเก็ตก่อนจึงจะยอมรับการเชื่อมต่อได้นอกจากนี้ยังสร้างช่องสัญญาณใหม่โดยเรียกใช้เมธอด openServerSocketChannel ของอ็อบเจ็กต์ SelectorProvider ดีฟอลต์ทั้งระบบ

เช่นเดียวกับช่องซ็อกเก็ตเซิร์ฟเวอร์ซ็อกเก็ตช่องสัญญาณสามารถอ่านข้อมูลได้ read()วิธีการประการแรกบัฟเฟอร์ถูกจัดสรร ข้อมูลที่อ่านจาก ServerSocketChannel จะถูกเก็บไว้ในบัฟเฟอร์ประการที่สองเราเรียกว่าเมธอด ServerSocketChannel.read () และอ่านข้อมูลจาก ServerSocketChannel ลงในบัฟเฟอร์ ค่าจำนวนเต็มของเมธอด read () จะส่งกลับจำนวนไบต์ที่เขียนลงในบัฟเฟอร์

ข้อมูลในทำนองเดียวกันสามารถเขียนไปยังช่องซ็อกเก็ตเซิร์ฟเวอร์โดยใช้ write() วิธีการใช้บัฟเฟอร์เป็นพารามิเตอร์โดยทั่วไปจะใช้วิธีการเขียนใน while loop เนื่องจากจำเป็นต้องทำซ้ำเมธอด write () จนกว่าบัฟเฟอร์จะไม่มีไบต์เพิ่มเติมให้เขียน

วิธีการสำคัญของ Socket channel

  • bind(SocketAddress local) - วิธีนี้ใช้เพื่อผูกช่องซ็อกเก็ตกับโลคัลแอดเดรสซึ่งจัดเตรียมไว้เป็นพารามิเตอร์ของเมธอดนี้

  • accept() - วิธีนี้ใช้เพื่อยอมรับการเชื่อมต่อกับซ็อกเก็ตของช่องนี้

  • connect(SocketAddress remote) - วิธีนี้ใช้เพื่อเชื่อมต่อซ็อกเก็ตกับที่อยู่ระยะไกล

  • finishConnect() - วิธีนี้ใช้เพื่อเสร็จสิ้นขั้นตอนการเชื่อมต่อช่องซ็อกเก็ต

  • getRemoteAddress() - วิธีนี้จะส่งกลับที่อยู่ของตำแหน่งระยะไกลที่เชื่อมต่อซ็อกเก็ตของช่อง

  • isConnected() - ดังที่ได้กล่าวไปแล้ววิธีนี้จะคืนสถานะการเชื่อมต่อของช่องซ็อกเก็ตเช่นเชื่อมต่อหรือไม่

  • open() - ใช้วิธีการเปิดเพื่อเปิดช่องซ็อกเก็ตโดยไม่มีที่อยู่ที่ระบุวิธีการอำนวยความสะดวกนี้ทำงานเหมือนกับการเรียกใช้เมธอด open () เรียกใช้วิธีการเชื่อมต่อกับช่องสัญญาณซ็อกเก็ตเซิร์ฟเวอร์ที่เป็นผลลัพธ์ส่งผ่านรีโมตแล้วส่งคืนช่องนั้น

  • read(ByteBuffer dst) - วิธีนี้ใช้เพื่ออ่านข้อมูลจากบัฟเฟอร์ที่กำหนดผ่านช่องซ็อกเก็ต

  • setOption(SocketOption<T> name, T value) - วิธีนี้ตั้งค่าตัวเลือกซ็อกเก็ต

  • socket() - วิธีนี้จะดึงซ็อกเก็ตเซิร์ฟเวอร์ที่เกี่ยวข้องกับแชนเนลนี้

  • validOps() - วิธีนี้ส่งคืนชุดการดำเนินการที่ระบุการดำเนินการที่รองรับของช่องสัญญาณนี้ช่องเซิร์ฟเวอร์ - ซ็อกเก็ตรองรับเฉพาะการยอมรับการเชื่อมต่อใหม่ดังนั้นวิธีนี้จะส่งกลับ SelectionKey.OP_ACCEPT

ตัวอย่าง

ตัวอย่างต่อไปนี้แสดงวิธีการส่งข้อมูลจาก Java NIO ServerSocketChannel

C: /Test/temp.txt

Hello World!

ไคลเอนต์: SocketChannelClient.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.EnumSet;

public class SocketChannelClient {
   public static void main(String[] args) throws IOException {
      ServerSocketChannel serverSocket = null;
      SocketChannel client = null;
      serverSocket = ServerSocketChannel.open();
      serverSocket.socket().bind(new InetSocketAddress(9000));
      client = serverSocket.accept();
      System.out.println("Connection Set:  " + client.getRemoteAddress());
      Path path = Paths.get("C:/Test/temp1.txt");
      FileChannel fileChannel = FileChannel.open(path, 
         EnumSet.of(StandardOpenOption.CREATE, 
            StandardOpenOption.TRUNCATE_EXISTING,
            StandardOpenOption.WRITE)
         );      
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(client.read(buffer) > 0) {
         buffer.flip();
         fileChannel.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Received");
      client.close();
   }
}

เอาต์พุต

การรันไคลเอนต์จะไม่พิมพ์อะไรเลยจนกว่าเซิร์ฟเวอร์จะเริ่มทำงาน

เซิร์ฟเวอร์: SocketChannelServer.java

import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.SocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Path;
import java.nio.file.Paths;

public class SocketChannelServer {
   public static void main(String[] args) throws IOException {
      SocketChannel server = SocketChannel.open();
      SocketAddress socketAddr = new InetSocketAddress("localhost", 9000);
      server.connect(socketAddr);
      Path path = Paths.get("C:/Test/temp.txt");
      FileChannel fileChannel = FileChannel.open(path);
      ByteBuffer buffer = ByteBuffer.allocate(1024);
      while(fileChannel.read(buffer) > 0) {
         buffer.flip();
         server.write(buffer);
         buffer.clear();
      }
      fileChannel.close();
      System.out.println("File Sent");
      server.close();
   }
}

เอาต์พุต

การรันเซิร์ฟเวอร์จะพิมพ์สิ่งต่อไปนี้

Connection Set:  /127.0.0.1:49558
File Received