Перейти к основному содержимому
claw
am
tools
Инструменты
Документы
Daoark
EN
Главная
Главная
/
Сетевые инструменты
›
' + '
' + labels[s] + '
' + '
URL: ' + (ws ? ws.url : '-') + '
' + '
' + '
' + '
握手耗时
' + (handshakeMs || '-') + ' ms
' + '
已发送
' + sentBytes + ' B
' + '
已接收
' + recvBytes + ' B
' + '
消息数
' + msgList.length + '
' + '
' + '
' + '
'; resultContent.innerHTML = html; var ml = document.getElementById('msgList'); msgList.forEach(function(m) { var div = document.createElement('div'); div.className = 'msg-item ' + m.dir + (m.type === 'binary' ? ' binary' : ''); var meta = '[' + m.dir === 'out' ? '↑ 发送' : '↓ 接收'; meta += ' · ' + m.type; meta += ' · ' + m.time; meta += ' · ' + m.size + ' B]'; div.innerHTML = '
' + meta + '
' + m.text; ml.appendChild(div); }); ml.scrollTop = ml.scrollHeight; var inlineInput = document.getElementById('msgInputInline'); if (inlineInput) { inlineInput.addEventListener('keydown', function(ev) { if (ev.key === 'Enter' && ws && ws.readyState === 1) { sendText(inlineInput.value); inlineInput.value = ''; } }); } } function appendMsg(dir, type, data, size) { var text; if (type === 'binary') { if (data instanceof ArrayBuffer) { var arr = new Uint8Array(data); var preview = []; for (var i = 0; i < Math.min(arr.length, 32); i++) preview.push(arr[i]); text = '[ArrayBuffer ' + arr.length + ' bytes] ' + preview.map(function(b){return b.toString(16).padStart(2,'0');}).join(' '); } else if (data instanceof Blob) { text = '[Blob ' + data.size + ' bytes]'; } else { text = '[Binary]'; } } else { text = String(data).substring(0, 500); } msgList.push({dir: dir, type: type, text: text.replace(/&/g,'&').replace(/ 100) msgList.shift(); } function sendText(text) { if (!ws || ws.readyState !== 1) return; try { ws.send(text); var size = (new TextEncoder().encode(text)).length; sentBytes += size; appendMsg('out', 'text', text, size); setStatus('open'); } catch (err) { errorMsg.textContent = '发送错误: ' + err.message; } } function sendBinary(text) { if (!ws || ws.readyState !== 1) return; try { var enc = new TextEncoder().encode(text); ws.send(enc); sentBytes += enc.length; appendMsg('out', 'binary', enc.buffer, enc.length); setStatus('open'); } catch (err) { errorMsg.textContent = '发送错误: ' + err.message; } } function connect(url) { if (ws) { try { ws.close(); } catch(e){} ws = null; } sentBytes = 0; recvBytes = 0; msgList = []; handshakeMs = 0; setStatus('connecting'); btnMain.disabled = true; btnDisconnect.disabled = false; btnSend.disabled = true; btnSendBin.disabled = true; errorMsg.textContent = ''; try { handshakeStart = Date.now(); ws = new WebSocket(url); ws.binaryType = 'arraybuffer'; ws.onopen = function() { handshakeMs = Date.now() - handshakeStart; btnMain.disabled = true; btnDisconnect.disabled = false; btnSend.disabled = false; btnSendBin.disabled = false; setStatus('open'); }; ws.onmessage = function(ev) { if (typeof ev.data === 'string') { var size = (new TextEncoder().encode(ev.data)).length; recvBytes += size; appendMsg('in', 'text', ev.data, size); } else { var arr = ev.data; var s = (arr && arr.byteLength) || (arr && arr.size) || 0; recvBytes += s; appendMsg('in', 'binary', arr, s); } setStatus('open'); }; ws.onerror = function() { errorMsg.textContent = '连接错误 (可能是 CORS、网络或目标不可达)'; }; ws.onclose = function(ev) { btnMain.disabled = false; btnDisconnect.disabled = true; btnSend.disabled = true; btnSendBin.disabled = true; setStatus('closed'); if (ev && ev.code) { errorMsg.textContent = '已断开 (code=' + ev.code + (ev.reason ? ', reason=' + ev.reason : '') + ')'; } }; } catch (err) { errorMsg.textContent = '连接异常: ' + err.message; btnMain.disabled = false; btnDisconnect.disabled = true; setStatus('closed'); } } function disconnect() { if (ws) { try { ws.close(1000, '用户主动断开'); } catch(e){} } } document.getElementById('f').addEventListener('submit', function(e) { e.preventDefault(); errorMsg.textContent = ''; var url = urlInput.value.trim(); if (!url) { errorMsg.textContent = '请输入 WebSocket URL'; return; } if (!/^wss?:\/\//i.test(url)) { errorMsg.textContent = 'URL 必须以 ws:// 或 wss:// 开头'; return; } resultArea.classList.add('show'); connect(url); }); btnDisconnect.addEventListener('click', disconnect); btnSend.addEventListener('click', function() { sendText(msgInput.value); }); btnSendBin.addEventListener('click', function() { sendBinary(msgInput.value); }); msgInput.addEventListener('keydown', function(ev) { if (ev.key === 'Enter' && ws && ws.readyState === 1) { sendText(msgInput.value); msgInput.value = ''; } }); // 初始状态展示 setStatus('closed'); })();