รับเหตุผลว่าทำไม websockets ปิดด้วยรหัสปิด 1006


92

ฉันต้องการทราบเหตุผลที่ websockets ปิดดังนั้นฉันจึงสามารถแสดงข้อความที่ถูกต้องให้กับผู้ใช้

ฉันมี

sok.onerror=function (evt) 
     {//since there is an error, sockets will close so...
       sok.onclose=function(e){
           console.log("WebSocket Error: " , e);}

รหัสคือ 1006 เสมอและเหตุผลคือ "" เสมอ แต่ฉันต้องการบอกเหตุผลในการปิดที่แตกต่างกันออกไป

ตัวอย่างเช่นบรรทัด comand ให้เหตุผลข้อผิดพลาด: "คุณไม่สามารถลบสิ่งนั้นได้เนื่องจากฐานข้อมูลไม่ยอมให้คุณ" แต่ในคอนโซลของ Chrome เหตุผลยังคงเป็น ""

มีวิธีอื่นในการบอกเหตุผลการปิดที่แตกต่างออกไปไหม


ฉันคิดว่านี่เป็นเพราะเซิร์ฟเวอร์จัดการกับเหตุการณ์ที่เชื่อมต่อ / ตัดการเชื่อมต่ออย่างไร ฉันไม่สามารถพูดได้อย่างแน่นอน แต่การปิดการเชื่อมต่อต้องได้รับการจัดการอย่างถูกต้องบนเซิร์ฟเวอร์ด้วยรหัส ลองลบล้างเมธอด On Connected / Disconnected ในตัวบนเซิร์ฟเวอร์และดู ข้อสันนิษฐานของฉันเพียงว่าคุณกำลังปิด แต่เซิร์ฟเวอร์ไม่ได้ปิดอย่างถูกต้องดังนั้นจึงไม่ถ่ายทอดการตอบสนองแบบปิดที่เหมาะสม
Michael Puckett II

คำตอบ:


124

Close Code1006เป็นรหัสพิเศษที่หมายความว่าการเชื่อมต่อถูกปิดอย่างผิดปกติ (ในเครื่อง) โดยการใช้งานเบราว์เซอร์

หากไคลเอนต์เบราว์เซอร์ของคุณรายงานโค้ดปิด1006คุณควรดูwebsocket.onerror(evt)รายละเอียดที่เหตุการณ์

อย่างไรก็ตาม Chrome จะไม่ค่อยรายงาน1006เหตุผลการปิดโค้ดใด ๆให้กับฝั่ง Javascript อาจเกิดจากกฎความปลอดภัยของไคลเอ็นต์ในข้อกำหนด WebSocket เพื่อป้องกันการใช้ WebSocket ในทางที่ผิด (เช่นใช้เพื่อสแกนหาพอร์ตที่เปิดอยู่บนเซิร์ฟเวอร์ปลายทางหรือเพื่อสร้างการเชื่อมต่อจำนวนมากสำหรับการโจมตีแบบปฏิเสธการให้บริการ)

โปรดทราบว่า Chrome มักจะรายงานรหัสปิด1006หากมีข้อผิดพลาดระหว่างการอัปเกรด HTTP เป็น Websocket (นี่เป็นขั้นตอนก่อนที่ WebSocket จะ "เชื่อมต่อ" ในทางเทคนิค) ด้วยเหตุผลเช่นการตรวจสอบสิทธิ์หรือการอนุญาตที่ไม่ถูกต้องหรือการใช้โปรโตคอลที่ไม่ถูกต้อง (เช่นการขอโปรโตคอลย่อย แต่เซิร์ฟเวอร์เองไม่รองรับโปรโตคอลย่อยเดียวกันนั้น) หรือแม้แต่ความพยายามในการพูดคุยกับตำแหน่งเซิร์ฟเวอร์ที่ไม่ใช่ WebSocket ( เช่นพยายามเชื่อมต่อws://images.google.com/)

โดยพื้นฐานแล้วหากคุณเห็นรหัสปิดแสดง1006ว่าคุณมีข้อผิดพลาดระดับต่ำมากกับ WebSocket เอง (คล้ายกับ "ไม่สามารถเปิดไฟล์" หรือ "ข้อผิดพลาดของซ็อกเก็ต") ซึ่งไม่ได้มีไว้สำหรับผู้ใช้อย่างแท้จริงเนื่องจากชี้ไปที่ปัญหาระดับต่ำ ด้วยรหัสและการใช้งานของคุณ แก้ไขปัญหาระดับต่ำของคุณจากนั้นเมื่อคุณเชื่อมต่อแล้วคุณสามารถใส่รหัสข้อผิดพลาดที่สมเหตุสมผลมากขึ้นได้ คุณสามารถทำสิ่งนี้ให้สำเร็จได้ในแง่ของขอบเขตหรือความรุนแรงในโครงการของคุณ ตัวอย่าง: ข้อมูลและระดับการเตือนเป็นส่วนหนึ่งของโปรโตคอลเฉพาะของโปรเจ็กต์ของคุณและจะไม่ทำให้การเชื่อมต่อยุติลง ด้วยการรายงานข้อความที่รุนแรงหรือถึงแก่ชีวิตนอกจากนี้ยังใช้โปรโตคอลของโปรเจ็กต์ของคุณเพื่อถ่ายทอดรายละเอียดได้มากเท่าที่คุณต้องการจากนั้นจึงปิดการเชื่อมต่อโดยใช้ความสามารถที่ จำกัด ของขั้นตอนการปิด WebSocket

โปรดทราบว่ารหัสปิด WebSocket มีการกำหนดไว้อย่างเคร่งครัดและวลี / ข้อความเหตุผลปิดต้องมีความยาวไม่เกิน 123 อักขระ (นี่คือข้อ จำกัด ของ WebSocket โดยเจตนา)

แต่ไม่ใช่ทั้งหมดจะหายไปหากคุณเพียงแค่ต้องการข้อมูลนี้เพื่อเหตุผลในการดีบักรายละเอียดของการปิดและเหตุผลพื้นฐานมักจะถูกรายงานพร้อมรายละเอียดที่เป็นธรรมในคอนโซล Javascript ของ Chrome


4
Joakim ขอบคุณผู้ตอบที่ละเอียดมาก ถ้าใช้sok.onerror=function (evt) {console.log(evt);}แล้วรายละเอียดไม่มาก ไม่ได้reasonหรืออะไร ไม่มีตัวเลือกเลยเหรอ? ฉันแค่แสดงให้ผู้ใช้เห็นsomething is wrong, or not connencted?ไม่เป็นมิตรกับผู้ใช้มันคงจะดีถ้าผู้ใช้เห็น "คุณไม่สามารถลบสาเหตุของข้อ จำกัด ของฐานข้อมูล" ตัวเลือกใด ๆ ขอบคุณ
slevin

คุณควรใช้sok.oncloseแทนซึ่งทริกเกอร์close eventมีreasonและcodeอยู่ในนั้น
Ihab Khattab

@IhabKhattab ที่จะเป็นรหัสเฉพาะและเมื่อการปิดเกิดขึ้น การมีsok.oncloseจะใช้งานได้หลายเส้นทาง แต่ไม่ใช่ทุกเส้นทาง โดยเฉพาะโปรโตคอลที่ไม่ดีข้อผิดพลาดในการจับมือที่ไม่ดี (เช่นเงื่อนไขบางอย่างที่อาจทำให้รหัสปิด1006) สิ่งนี้จะเปลี่ยนแปลงในอนาคตหรือไม่? อาจ. แต่เมื่อคำตอบนี้ถูกเขียนขึ้นมันเป็นความจริง
Joakim Erdfelt

@JoakimErdfelt ขอโทษฉันตอบคำถาม @slevin เกี่ยวกับเขาไม่ได้reasonคืนเมื่อเขาใช้onerrorฉันชี้ว่าคุณสมบัตินี้code& reasonเฉพาะกับcloseเหตุการณ์ไม่ใช่errorเหตุการณ์ ดังนั้นมันจะดีกว่าให้เขาใช้oncloseแทนฉันขาดอะไรไปหรือเปล่า?
Ihab Khattab

@IhabKhattab ใช่เนื่องจากคำถามของเขาเจาะจงเกี่ยวกับรหัสข้อผิดพลาด1006ซึ่งมีความหมายพิเศษและการจัดการพิเศษในข้อมูลจำเพาะ websocket และ javascript websocket api สตริง / ข้อความเหตุผลภายใต้1006เงื่อนไขบางประการมีไว้โดยเฉพาะและไม่ได้ตั้งใจเปิดเผยที่ใดก็ได้ใน API (ตามที่คำตอบชี้ให้เห็น) นี่ไม่ใช่ข้อบกพร่องใน API เป็นเพียงการระบุรายละเอียดต่างๆและข้อกังวลเกี่ยวกับการใช้ websocket ในทางที่ผิดเพื่อจุดประสงค์ที่ไม่ใช่ websocket
Joakim Erdfelt

16

ในกรณีของฉันและอาจ @BIOHAZARD nginx proxy timeoutมันเป็น โดยค่าเริ่มต้นเป็น60วินาทีโดยไม่มีกิจกรรมในซ็อกเก็ต

ฉันเปลี่ยนเป็น 24 ชม. nginxและแก้ไขปัญหาได้

proxy_read_timeout 86400s;
proxy_send_timeout 86400s;

ขอบคุณสำหรับสิ่งนี้! เป็นสาเหตุของข้อผิดพลาด 1006 ในกรณีของฉัน
Steve Hanov

11

ดูเหมือนว่าจะเป็นกรณีนี้เมื่อ Chrome ไม่เป็นไปตามมาตรฐาน WebSocket เมื่อเซิร์ฟเวอร์เริ่มปิดและส่งเฟรมปิดไปยังไคลเอนต์ Chrome จะถือว่านี่เป็นข้อผิดพลาดและรายงานไปยังฝั่ง JS ด้วยรหัส 1006 และไม่มีข้อความแสดงเหตุผล ในการทดสอบของฉัน Chrome ไม่ตอบสนองต่อเฟรมปิดที่เริ่มต้นโดยเซิร์ฟเวอร์ (รหัสปิด 1000) โดยบอกว่ารหัส 1006 อาจหมายความว่า Chrome กำลังรายงานข้อผิดพลาดภายในของตัวเอง

PS Firefox v57.00 จัดการกรณีนี้อย่างถูกต้องและส่งข้อความเหตุผลของเซิร์ฟเวอร์ไปยังฝั่ง JS ได้สำเร็จ


3

คิดว่านี่อาจเป็นประโยชน์สำหรับคนอื่น ๆ เด็ก ๆ รู้ว่านิพจน์ทั่วไปมีประโยชน์ อยู่ในโรงเรียน.

แก้ไข: เปลี่ยนเป็นฟังก์ชันสำรวยที่มีประโยชน์!

let specificStatusCodeMappings = {
    '1000': 'Normal Closure',
    '1001': 'Going Away',
    '1002': 'Protocol Error',
    '1003': 'Unsupported Data',
    '1004': '(For future)',
    '1005': 'No Status Received',
    '1006': 'Abnormal Closure',
    '1007': 'Invalid frame payload data',
    '1008': 'Policy Violation',
    '1009': 'Message too big',
    '1010': 'Missing Extension',
    '1011': 'Internal Error',
    '1012': 'Service Restart',
    '1013': 'Try Again Later',
    '1014': 'Bad Gateway',
    '1015': 'TLS Handshake'
};

function getStatusCodeString(code) {
    if (code >= 0 && code <= 999) {
        return '(Unused)';
    } else if (code >= 1016) {
        if (code <= 1999) {
            return '(For WebSocket standard)';
        } else if (code <= 2999) {
            return '(For WebSocket extensions)';
        } else if (code <= 3999) {
            return '(For libraries and frameworks)';
        } else if (code <= 4999) {
            return '(For applications)';
        }
    }
    if (typeof(specificStatusCodeMappings[code]) !== 'undefined') {
        return specificStatusCodeMappings[code];
    }
    return '(Unknown)';
}

การใช้งาน:

getStatusCodeString(1006); //'Abnormal Closure'

{
    '0-999': '(Unused)',
    '1016-1999': '(For WebSocket standard)',
    '2000-2999': '(For WebSocket extensions)',
    '3000-3999': '(For libraries and frameworks)',
    '4000-4999': '(For applications)'
}

{
    '1000': 'Normal Closure',
    '1001': 'Going Away',
    '1002': 'Protocol Error',
    '1003': 'Unsupported Data',
    '1004': '(For future)',
    '1005': 'No Status Received',
    '1006': 'Abnormal Closure',
    '1007': 'Invalid frame payload data',
    '1008': 'Policy Violation',
    '1009': 'Message too big',
    '1010': 'Missing Extension',
    '1011': 'Internal Error',
    '1012': 'Service Restart',
    '1013': 'Try Again Later',
    '1014': 'Bad Gateway',
    '1015': 'TLS Handshake'
}

ที่มา (พร้อมการแก้ไขเล็กน้อยสำหรับความสั้น): https://developer.mozilla.org/en-US/docs/Web/API/CloseEvent#Status_codes


1

ฉันพบข้อผิดพลาดขณะใช้ Chrome เป็นไคลเอนต์และ golang gorilla websocket เป็นเซิร์ฟเวอร์ภายใต้พร็อกซี nginx

และการส่งข้อความ "ping" บางส่วนจากเซิร์ฟเวอร์ไปยังไคลเอนต์ทุกๆ x วินาทีสามารถแก้ไขปัญหาได้


0

นี่อาจเป็น URL websocket ของคุณที่คุณใช้ในอุปกรณ์ไม่เหมือนกัน (คุณกำลังกดปุ่ม websocket URL ที่แตกต่างจาก android / iphonedevice)

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