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