การโทรแบบขนานเพื่อส่ง / รับสัญญาณบนซ็อกเก็ตเดียวกันถูกต้องหรือไม่


127
  1. เราสามารถเรียกส่งจากเธรดหนึ่งและรับจากอีกเธรดหนึ่งบนซ็อกเก็ตเดียวกันได้หรือไม่?
  2. เราสามารถเรียกการส่งหลายรายการแบบคู่ขนานจากเธรดที่แตกต่างกันบนซ็อกเก็ตเดียวกันได้หรือไม่

ฉันรู้ว่าการออกแบบที่ดีควรหลีกเลี่ยงสิ่งนี้ แต่ฉันไม่ชัดเจนว่า API ของระบบเหล่านี้จะทำงานอย่างไร ฉันไม่พบเอกสารที่ดีสำหรับเรื่องเดียวกันนี้

ตัวชี้ทิศทางใด ๆ จะเป็นประโยชน์


3
ทำไมคุณถึงอ้างว่าการทำเช่นนั้นเป็นการปฏิบัติที่ไม่ดี?. มันดูดีสำหรับฉันเพราะคุณฟังและรับจากกระทู้ที่แตกต่างกัน
TheMathNoob

คำตอบ:


92

POSIX กำหนด send / recv เป็นการดำเนินการแบบปรมาณูดังนั้นสมมติว่าคุณกำลังพูดถึง POSIX send / recv ใช่แล้วคุณสามารถเรียกใช้พร้อมกันจากหลายเธรดและสิ่งต่างๆจะทำงานได้

ซึ่งไม่ได้หมายความว่าจะดำเนินการควบคู่กันไป - ในกรณีของการส่งหลายครั้งการส่งครั้งที่สองอาจจะบล็อกจนกว่าการส่งครั้งแรกจะเสร็จสมบูรณ์ คุณอาจไม่สังเกตเห็นสิ่งนี้มากนักเนื่องจากการส่งเสร็จสมบูรณ์เมื่อใส่ข้อมูลลงในบัฟเฟอร์ซ็อกเก็ต

หากคุณใช้ซ็อกเก็ต SOCK_STREAM การพยายามทำสิ่งต่างๆแบบขนานมีโอกาสน้อยที่จะมีประโยชน์เนื่องจาก send / recv อาจส่งหรือรับเพียงบางส่วนของข้อความซึ่งหมายความว่าสิ่งต่างๆอาจแยกออกจากกันได้

การบล็อกการส่ง / รับข้อมูลบนซ็อกเก็ต SOCK_STREAM จะบล็อกจนกว่าจะส่งหรือรับข้อมูลอย่างน้อย 1 ไบต์ดังนั้นความแตกต่างระหว่างการบล็อกและการไม่บล็อกจึงไม่มีประโยชน์


1
@Joao: ซ็อกเก็ต SOCK_DGRAM ได้รับการบันทึกว่า "รักษาขอบเขตข้อความ" ซึ่งไม่ชัดเจนมากนัก จากการดูแหล่งที่มาของเคอร์เนล linux อย่างน้อยคุณจะเห็นได้ว่าการส่งและรับแต่ละรายการเกี่ยวข้องกับแพ็กเก็ตเดียวแบบ atomically (อย่างน้อยสำหรับ udp)
Chris Dodd

2
@Kedar: ไม่แน่ใจว่าคุณหมายถึงอะไร sendผลตอบแทนเร็วที่สุดเท่าที่ข้อมูลจะถูกวางลงในบัฟเฟอร์ส่งและข้อมูลที่ถูกส่งผ่านสแต็ค netowrk และออกไปยังเครือข่ายถ่ายทอดสด ดังนั้นหากคุณมีการส่งเธรดหนึ่งเธรดและการรับเธรดหนึ่งเธรดจึงเป็นไปได้ทั้งหมด (อาจเป็นไปได้) ที่เธรดการส่งจะส่งแพ็กเก็ตจำนวนมากก่อนที่เธรดการรับจะได้รับแพ็กเก็ตแรก ไม่ตรงกันทั้งหมดและไม่พร้อมกัน
Chris Dodd

6
@ChrisDodd คุณสามารถให้ลิงก์สำหรับ "POSIX กำหนดการส่ง / รับเป็นการดำเนินการของอะตอม" ได้หรือไม่
suitianshi

2
@suitianshi: เอกสารมาตรฐาน POSIX 1003.1c แสดงรายการฟังก์ชันทั้งหมดใน 1003.1 ที่ reentrant (ปลอดภัยในการเรียกจากเธรด) และสิ่งใดที่ไม่ใช่ ฉันไม่ทราบว่ามีสำเนาออนไลน์ฟรีทุกที่น่าเสียดาย
Chris Dodd

2
@ChrisDodd ฉันพบสำเนาในunix-systems.org/version4และฉันสามารถดูรายการของตารางอินเทอร์เฟซระบบในบทที่ 7.1 แต่ไม่เห็นว่ามันแสดงรายการฟังก์ชันว่าเป็นการดำเนินการของอะตอม เพื่อไม่ให้คุณสงสัย แต่คุณสามารถแบ่งปัน / แก้ไขคำตอบของคุณเพื่อพิสูจน์ประเด็นของคุณในเอกสารได้หรือไม่?
user153882

17

ตัวบอกซ็อกเก็ตเป็นของกระบวนการไม่ใช่ของเธรดใดเธรดหนึ่ง ดังนั้นจึงเป็นไปได้ที่จะส่ง / รับไปยัง / จากซ็อกเก็ตเดียวกันในเธรดที่แตกต่างกันระบบปฏิบัติการจะจัดการการซิงโครไนซ์

อย่างไรก็ตามหากลำดับการส่ง / รับมีนัยสำคัญทางความหมายคุณเอง (ตามลำดับรหัสของคุณ) จะต้องตรวจสอบให้แน่ใจว่ามีการจัดลำดับที่เหมาะสมระหว่างการดำเนินการในเธรดที่แตกต่างกันเช่นเดียวกับในกรณีของเธรด


4

ฉันไม่เห็นว่าการรับแบบขนานจะทำอะไรได้สำเร็จ หากคุณมีข้อความ 3 ไบต์ 1 เธรดจะได้รับ 2 ไบต์แรกและอีกไบต์สุดท้าย แต่คุณไม่มีทางบอกได้ว่าอันไหน เว้นแต่ข้อความของคุณจะมีความยาวเพียงไบต์ไม่มีวิธีใดที่คุณจะสามารถทำให้ทุกอย่างทำงานได้อย่างน่าเชื่อถือกับการรับหลายเธรด

การส่งหลายครั้งอาจใช้งานได้หากคุณส่งทั้งข้อความในการโทรครั้งเดียว แต่ฉันไม่แน่ใจ เป็นไปได้ว่าอาจเขียนทับอีกอันหนึ่งได้ การทำเช่นนั้นจะไม่มีประโยชน์อย่างแน่นอน

หากต้องส่งหลายเธรดคุณควรใช้คิวข้อความที่ซิงโครไนซ์ มีเธรดหนึ่งเธรดที่ทำการส่งจริงซึ่งอ่านข้อความจากคิวและมีเธรดอื่น ๆ จัดคิวข้อความทั้งหมด สิ่งเดียวกันนี้จะใช้ได้สำหรับการรับ แต่เธรดรับจะต้องรู้รูปแบบของข้อความเพื่อที่จะได้แยกส่วนออกอย่างถูกต้อง


9
หากคุณใช้ซ็อกเก็ต SOCK_DGRAM แต่ละ recv จะได้รับดาตาแกรมเดียว มันจะไม่มีทางแยกระหว่าง recvs
Chris Dodd

2
@noah ฉันยอมรับว่าการรับแบบขนานไม่สามารถทำอะไรได้สำเร็จ นั่นเป็นเหตุผลที่ฉันไม่ได้ถามมัน คำถามของฉันคือ send / recv แบบคู่ขนานแล้วส่งหลายรายการคู่ขนานกัน คำตอบของคุณให้ข้อมูลเชิงลึกเกี่ยวกับการส่งคู่ขนาน ขอบคุณสำหรับสิ่งเดียวกัน
เจ

1
@ คริสจุดดี. ฉันสมมติว่า TCP @Jay คุณอาจจะชี้แจงคำถาม "เราสามารถโทรส่ง / รับคู่ขนานกันได้ไหม" ดูเหมือนว่าคุณต้องการรับแบบขนาน
noah
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.