1. ปัญหาหลักสองประการในการเขียนโปรแกรมเครือข่าย
หนึ่งคือวิธีการค้นหาโฮสต์อย่างน้อยหนึ่งรายการในเครือข่ายและอีกอย่างคือวิธีการส่งข้อมูลอย่างน่าเชื่อถือและมีประสิทธิภาพหลังจากค้นหาโฮสต์
ในโปรโตคอล TCP/IP ชั้น IP ส่วนใหญ่รับผิดชอบตำแหน่งของโฮสต์เครือข่ายและการกำหนดเส้นทางของการส่งข้อมูล ที่อยู่ IP สามารถกำหนดโฮสต์บนอินเทอร์เน็ตได้โดยเฉพาะ
เลเยอร์ TCP มีกลไกการส่งข้อมูลที่เชื่อถือได้ (TCP) หรือไม่น่าเชื่อถือ (UDP) สำหรับแอปพลิเคชันซึ่งเป็นวัตถุหลักของการเขียนโปรแกรมเครือข่ายและโดยทั่วไปไม่จำเป็นต้องใส่ใจเกี่ยวกับวิธีการประมวลผลข้อมูลเลเยอร์ IP
รูปแบบการเขียนโปรแกรมเครือข่ายที่ได้รับความนิยมมากที่สุดในปัจจุบันคือโครงสร้างไคลเอนต์/เซิร์ฟเวอร์ (c/s) นั่นคือหนึ่งในฝ่ายสื่อสารทำหน้าที่เป็นเซิร์ฟเวอร์เพื่อรอให้ลูกค้าส่งคำขอและตอบกลับ ลูกค้าใช้กับเซิร์ฟเวอร์เมื่อต้องการบริการ โดยทั่วไปเซิร์ฟเวอร์มักจะทำงานเป็น daemon โดยฟังพอร์ตเครือข่าย เมื่อลูกค้าร้องขอมันจะเริ่มกระบวนการบริการเพื่อตอบสนองต่อลูกค้าและในขณะเดียวกันก็ยังคงฟังพอร์ตบริการต่อไปเพื่อให้ลูกค้าสามารถรับบริการได้ในเวลาที่เหมาะสม
2. โปรโตคอลการส่งผ่านสองประเภท: TCP; UDP
TCP เป็นตัวย่อของ Tranfer Control Protocol ซึ่งเป็นโปรโตคอลที่มุ่งเน้นการเชื่อมต่อที่ทำให้มั่นใจได้ว่าการส่งที่เชื่อถือได้ การส่งผ่านโปรโตคอล TCP ส่งผลให้เกิดกระแสข้อมูลที่ปราศจากข้อผิดพลาด จะต้องมีการเชื่อมต่อระหว่างซ็อกเก็ตสองคู่ของผู้ส่งและผู้รับเพื่อสื่อสารบนพื้นฐานของโปรโตคอล TCP เมื่อซ็อกเก็ตหนึ่ง (โดยปกติคือซ็อกเก็ตเซิร์ฟเวอร์) กำลังรอการสร้างการเชื่อมต่อซ็อกเก็ตอื่น ๆ อาจต้องมีการเชื่อมต่อ เมื่อเชื่อมต่อซ็อกเก็ตทั้งสองนี้พวกเขาสามารถทำการส่งข้อมูลแบบสองทางและทั้งสองฝ่ายสามารถดำเนินการส่งหรือรับการดำเนินการ
UDP เป็นตัวย่อของ User Datagram Protocol มันเป็นโปรโตคอลที่ไม่มีการเชื่อมต่อ แต่ละดาตาแกรมเป็นข้อมูลอิสระรวมถึงที่อยู่ที่สมบูรณ์หรือที่อยู่ปลายทาง มันถูกส่งไปยังปลายทางบนเครือข่ายโดยเส้นทางที่เป็นไปได้ ดังนั้นไม่ว่าจะไปถึงปลายทางเวลาในการไปถึงปลายทางและความถูกต้องของเนื้อหาไม่สามารถรับประกันได้
เปรียบเทียบ:
UDP:
TCP:
แอปพลิเคชัน:
3. การเขียนโปรแกรมเครือข่าย Java ที่ใช้ซ็อกเก็ต
1. ซ็อกเก็ตคืออะไร
สองโปรแกรมในเครือข่ายตระหนักถึงการแลกเปลี่ยนข้อมูลผ่านการเชื่อมต่อการสื่อสารสองทาง ปลายด้านหนึ่งของลิงค์สองทางนี้เรียกว่าซ็อกเก็ต ซ็อกเก็ตมักจะใช้เพื่อเชื่อมต่อระหว่างลูกค้าและผู้ให้บริการ ซ็อกเก็ตเป็นอินเทอร์เฟซการเขียนโปรแกรมยอดนิยมของโปรโตคอล TCP/IP ซ็อกเก็ตถูกกำหนดโดยที่อยู่ IP และหมายเลขพอร์ต
อย่างไรก็ตามประเภทของโปรโตคอลที่รองรับโดยซ็อกเก็ตไม่เพียง แต่ TCP/IP ดังนั้นจึงไม่มีการเชื่อมต่อที่จำเป็นระหว่างทั้งสอง ในสภาพแวดล้อม Java การเขียนโปรแกรมซ็อกเก็ตส่วนใหญ่หมายถึงการเขียนโปรแกรมเครือข่ายตามโปรโตคอล TCP/IP
2. กระบวนการสื่อสารซ็อกเก็ต
Server Side Listen (ฟัง) ว่ามีคำขอการเชื่อมต่อในพอร์ตหรือไม่ ด้านไคลเอนต์ออกคำขอเชื่อมต่อไปยังฝั่งเซิร์ฟเวอร์และฝั่งเซิร์ฟเวอร์ส่งข้อความตอบกลับกลับไปยังฝั่งไคลเอ็นต์ มีการสร้างการเชื่อมต่อ ทั้งเซิร์ฟเวอร์และฝั่งไคลเอ็นต์สามารถสื่อสารกันผ่านการส่งการเขียนและวิธีอื่น ๆ
สำหรับซ็อกเก็ตที่ใช้งานได้อย่างสมบูรณ์จะต้องมีโครงสร้างพื้นฐานต่อไปนี้และกระบวนการทำงานรวมถึงขั้นตอนพื้นฐานสี่ขั้นตอนต่อไปนี้:
(1) สร้างซ็อกเก็ต
(2) เปิดอินพุต/การไหลออกที่เชื่อมต่อกับซ็อกเก็ต
(3) อ่าน/เขียนซ็อกเก็ตตามโปรโตคอลที่แน่นอน
(4) ปิดซ็อกเก็ต (ในแอปพลิเคชันจริงการปิดที่แสดงไม่ได้ใช้แม้ว่าบทความจำนวนมากแนะนำสิ่งนี้ในโปรแกรมของฉันมันอาจไม่มีผลกระทบใด ๆ เนื่องจากโปรแกรมนั้นค่อนข้างง่ายและมีข้อกำหนดต่ำ
3. สร้างซ็อกเก็ต
ซ็อกเก็ต (ที่อยู่ inetaddress, พอร์ต int); ซ็อกเก็ต (ที่อยู่ inetaddress, พอร์ต int, สตรีมบูลีน); ซ็อกเก็ต (สตริงโฮสต์, int prot); ซ็อกเก็ต (โฮสต์สตริง, int prot, สตรีมบูลีน); ซ็อกเก็ต (SockketImpl INPL) ซ็อกเก็ต (สตริงโฮสต์, พอร์ต int, inetAddress localAddr, int localport) ซ็อกเก็ต (ที่อยู่ inetaddress, พอร์ต int, inetaddress localAddr, int localport) เซิร์ฟเวอร์ (พอร์ต int); Serversocket (พอร์ต int, backlog int); Serversocket (พอร์ต int, int backlog, inetaddress bindaddr) ที่ที่อยู่โฮสต์และพอร์ตคือที่อยู่ IP ชื่อโฮสต์และหมายเลขพอร์ตของบุคคลอื่นในการเชื่อมต่อแบบสองทิศทางตามลำดับ สตรีมระบุว่าซ็อกเก็ตเป็นซ็อกเก็ตสตรีมหรือซ็อกเก็ตดาต้าแกรม LocalPort ระบุหมายเลขพอร์ตของโฮสต์ท้องถิ่น LocalAddr และ Bindaddr เป็นที่อยู่ของเครื่องท้องถิ่น (ที่อยู่โฮสต์ของ Serversocket) Impl เป็นคลาสแม่ของซ็อกเก็ตซึ่งสามารถใช้ในการสร้าง Serversocket และสร้างซ็อกเก็ต Count แสดงถึงจำนวนการเชื่อมต่อสูงสุดที่เซิร์ฟเวอร์สามารถรองรับได้ ตัวอย่างเช่น: การเรียนรู้เครือข่ายวิดีโอ http://www.xxspw.com ซ็อกเก็ตไคลเอนต์ = ซ็อกเก็ตใหม่ ("127.0.01", 80); Serversocket Server = ใหม่ Serversocket (80);โปรดทราบว่าคุณต้องระวังเมื่อเลือกพอร์ต แต่ละพอร์ตให้บริการเฉพาะ โดยการให้พอร์ตที่ถูกต้องสามารถรับบริการที่เกี่ยวข้องได้ หมายเลขพอร์ตจาก 0 ~ 1023 สงวนไว้โดยระบบ ตัวอย่างเช่นหมายเลขพอร์ตของบริการ HTTP คือ 80 หมายเลขพอร์ตของบริการ Telnet คือ 21 และหมายเลขพอร์ตของบริการ FTP คือ 23 ดังนั้นเมื่อเราเลือกหมายเลขพอร์ตจะเป็นการดีที่สุดที่จะเลือกหมายเลขมากกว่า 1023 เพื่อป้องกันความขัดแย้ง
หากมีข้อผิดพลาดเกิดขึ้นเมื่อสร้างซ็อกเก็ต iOException จะถูกสร้างขึ้นและจะต้องดำเนินการในโปรแกรม ดังนั้นเมื่อสร้างซ็อกเก็ตหรือ Serversocket ต้องมีข้อยกเว้นหรือโยน
4. โปรแกรมไคลเอนต์/เซิร์ฟเวอร์ง่ายๆ
1. โปรแกรมลูกค้า
นำเข้า Java.io.*; นำเข้า Java.net.*; Public Class TalkClient {โมฆะสาธารณะคงที่หลัก (String args []) {ลอง {ซ็อกเก็ตซ็อกเก็ต = ซ็อกเก็ตใหม่ ("127.0.0.1", 4700); // ส่งคำขอไคลเอนต์ไปยังพอร์ต 4700 ของเครื่องบัฟเฟอร์เครื่องบัฟเฟอร์ SIN = ใหม่ bufferedReader (ใหม่ InputStreamReader (System.In)); // สร้างวัตถุ bufferedReader จากอุปกรณ์อินพุตมาตรฐานอุปกรณ์ printwriter os = printwriter ใหม่ (socket.getOutputStream ()); // รับกระแสเอาต์พุตจากวัตถุซ็อกเก็ตและสร้าง bufferedreader วัตถุ printwriter is = bufferedReader ใหม่ (InputStreamReader ใหม่ (socket.getInputStream ())); // รับสตรีมอินพุตจากวัตถุซ็อกเก็ตและสร้างสตริงวัตถุบัฟเฟอร์ที่สอดคล้องกันที่สอดคล้องกัน readLine = sin.readline (); // อ่านสตริงจากอินพุตมาตรฐานของระบบในขณะที่ (! readline.equals ("ลาก่อน")) {// ถ้าสตริงอ่านจากอินพุตมาตรฐานคือ "ลาก่อน" หยุดลูป os.println (readline); // เอาต์พุตสตริงอ่านจากอินพุตมาตรฐานของระบบไปยังเซิร์ฟเวอร์ os.flush (); // รีเฟรชสตรีมเอาต์พุตเพื่อให้เซิร์ฟเวอร์ได้รับสตริง System.out.println ทันที ("ไคลเอนต์:"+readline); // พิมพ์สตริงการอ่าน System.out.println ("เซิร์ฟเวอร์:"+is.readline ()); // อ่านสตริงจากเซิร์ฟเวอร์และพิมพ์ลงในมาตรฐาน output readline = sin.readline (); // อ่านสตริงจากอินพุตมาตรฐานของระบบ} // ดำเนินการต่อเพื่อวนซ้ำ OS.Close (); // ปิดสตรีมเอาต์พุตซ็อกเก็ตคือ. close (); // ปิดซ็อกเก็ตอินพุต Socket.close (); // ปิดซ็อกเก็ต} catch (exception e) {system.out.println ("ข้อผิดพลาด"+e); // เกิดข้อผิดพลาดข้อความแสดงข้อผิดพลาดจะถูกพิมพ์}}}2. โปรแกรมฝั่งเซิร์ฟเวอร์
นำเข้า Java.io.*; นำเข้า Java.net.*; นำเข้า java.applet.applet; Public Class Talkserver {Public Static Void Main (String args []) {ลอง {Serversocket Server = null; ลอง {server = ใหม่ Serversocket (4700); // สร้าง Serversocket เพื่อฟังคำขอของลูกค้าบนพอร์ต 4700} catch (Exception e) {system.out.println ("ไม่สามารถฟัง:"+e); // ข้อผิดพลาด, ข้อความแสดงข้อผิดพลาดพิมพ์} ซ็อกเก็ตซ็อกเก็ต = null; ลอง {socket = server.accept (); // ใช้ Accept () เพื่อบล็อกและรอคำขอลูกค้า หากไคลเอนต์ // หลังจากคำขอมาถึงวัตถุซ็อกเก็ตจะถูกสร้างขึ้นและดำเนินการต่อเพื่อดำเนินการ} catch (Exception e) {system.out.println ("ข้อผิดพลาด"+e); // เกิดข้อผิดพลาดข้อมูลข้อผิดพลาดการพิมพ์จะถูกพิมพ์} สายสตริง; bufferedReader คือ = ใหม่ bufferedReader (ใหม่ inputStreamReader (socket.getInputStream ())); // รับกระแสอินพุตจากวัตถุซ็อกเก็ตและสร้าง bufferedReader Object Printwriter OS = NEWPrintWriter (Socket.GetOutputStream ()); // รับกระแสเอาต์พุตจากวัตถุซ็อกเก็ตและสร้างวัตถุ printwriter bufferedReader sin = new bufferedReader (InputStreamReader ใหม่ (System.in)); // สร้าง bufferedReader object system.out.println ("ไคลเอนต์:"+is.readline ()); // พิมพ์สตริงที่อ่านจากไคลเอนต์บนบรรทัดเอาต์พุตมาตรฐาน = sin.readline (); // อ่านสตริงจากอินพุตมาตรฐานในขณะที่ (! line.equals ("ลาก่อน")) {// ถ้าสตริงคือ "ลาก่อน" หยุดลูป os.println (บรรทัด); // เอาต์พุตสตริง os.flush () ไปยังไคลเอนต์; // รีเฟรชสตรีมเอาต์พุตเพื่อให้ไคลเอนต์ได้รับสตริง System.out.println ทันที ("เซิร์ฟเวอร์:"+บรรทัด); // พิมพ์สตริงการอ่าน System.out.println ("ไคลเอนต์:"+is.readline ()); // อ่านสตริงจากไคลเอนต์และพิมพ์ไปยังบรรทัดเอาต์พุตมาตรฐาน = sin.readline (); // อ่านสตริงจากอินพุตมาตรฐานของระบบ} // ดำเนินการต่อเพื่อวนซ้ำ OS.Close (); // ปิดสตรีมเอาต์พุตซ็อกเก็ตคือ. close (); // ปิดซ็อกเก็ตอินพุต Socket.close (); // ปิดซ็อกเก็ตเซิร์ฟเวอร์ close (); // ปิด serversocket} catch (exception e) {system.out.println ("ข้อผิดพลาด:"+e); // เกิดข้อผิดพลาดข้อความแสดงข้อผิดพลาดพิมพ์}}}}5. สนับสนุนโปรแกรมไคลเอนต์/เซิร์ฟเวอร์หลายไคลเอนต์
โปรแกรมไคลเอนต์/เซิร์ฟเวอร์ก่อนหน้านี้สามารถใช้การสนทนาระหว่างเซิร์ฟเวอร์และลูกค้ารายหนึ่งเท่านั้น ในแอปพลิเคชันจริงโปรแกรมถาวรมักจะทำงานบนเซิร์ฟเวอร์ซึ่งสามารถรับคำขอจากลูกค้าอื่น ๆ หลายรายและให้บริการที่เกี่ยวข้อง เพื่อให้ตระหนักถึงฟังก์ชั่นของการให้บริการแก่ลูกค้าหลายรายบนเซิร์ฟเวอร์โปรแกรมข้างต้นจะต้องเปลี่ยนและมีการใช้กลไกมัลติเธรด เซิร์ฟเวอร์มักจะรับฟังว่ามีคำขอไคลเอนต์ในพอร์ตที่ระบุหรือไม่ เมื่อได้ยินคำขอไคลเอนต์เซิร์ฟเวอร์จะเริ่มเธรดบริการพิเศษเพื่อตอบสนองต่อคำขอของลูกค้า เซิร์ฟเวอร์เองเข้าสู่สถานะการฟังทันทีหลังจากเริ่มเธรดรอให้ไคลเอนต์ถัดไปมาถึง