Verbindungsproblem in der P2P-Chat-App auf Javascript und Python [geschlossen]Python

Python-Programme
Anonymous
 Verbindungsproblem in der P2P-Chat-App auf Javascript und Python [geschlossen]

Post by Anonymous »

Es gibt ein Problem mit dieser P2P-Chat-App, da immer keine Verbindung hergestellt werden kann. Ich habe diese App mit Hilfe von KI von chatgbt erstellt. Ich bin gut in Python, aber nicht gut genug, um mit JavaScript umzugehen. Ich habe die App je nach Funktion in mehrere Dateien aufgeteilt. Das Problem mit WebRTC liegt speziell in ICE. Ich habe den Ice-Server von Google hinzugefügt, aber es funktioniert immer noch nicht.

Code: Select all

    const wsUrl = "ws://localhost:8555";
let ws, pc, dc;
let myKey = null;
let myName = "";
let myPhone = "";
let myRoom = "main";
let currentTarget = null;
let map, markerCluster, mapRefreshInterval = null;
let pendingCandidates = [];
let connectionTimeout = null;

const config = {iceServers: [{ urls: "stun:stun.l.google.com:19302" }]};

webRTC

Code: Select all

async function createPC(isInitiator = false, targetKey = null) {
pc = new RTCPeerConnection(config);
pc.onicecandidate = e => e.candidate &&
ws.send(JSON.stringify({ action: "ice", data: e.candidate, target: targetKey, from: myKey }));

pc.ondatachannel = e => { dc = e.channel; setupDC(); };

pc.onconnectionstatechange = () => {
if (pc.connectionState === "connected") clearTimeout(connectionTimeout);
else if (pc.connectionState === "failed") updateConnectionStatus("failed");
else if (pc.connectionState === "disconnected") updateConnectionStatus("disconnected");
};

if (isInitiator) {
dc = pc.createDataChannel("chat");
setupDC();
}
}

function setupDC() {
dc.onopen = () => {
updateConnectionStatus("connected", currentTarget);
appendMsg("✅ تم إنشاء اتصال مباشر", "other");
if (connectionTimeout) {
clearTimeout(connectionTimeout);
connectionTimeout = null;
}
};

dc.onmessage = e => appendMsg(e.data, "other");
dc.onclose = () => updateConnectionStatus("disconnected");
dc.onerror = () => appendMsg("❌ خطأ في قناة الاتصال", "other");
}

async function startCall(targetKey) {
if (pc) pc.close();
if (dc) dc.close();
pendingCandidates = [];
currentTarget = targetKey.trim().toLowerCase();

updateConnectionStatus("connecting", currentTarget);
appendMsg(`🔄 جاري الاتصال بـ ${currentTarget}...`, "other");

connectionTimeout = setTimeout(() => {
if (!dc || dc.readyState !== "open") {
appendMsg("⏱️ انتهت مهلة الاتصال.", "other");
updateConnectionStatus("failed");
pc?.close();
}
}, 30000);

await createPC(true, currentTarget);
const offer = await pc.createOffer();
await pc.setLocalDescription(offer);
ws.send(JSON.stringify({ action: "offer", data: pc.localDescription, target: currentTarget, from: myKey }));
}

async function handleOffer(msg) {
currentTarget = msg.from;
showIncomingCallNotification(currentTarget);
playNotificationSound();

await createPC(false, currentTarget);
await pc.setRemoteDescription(msg.data);
const answer = await pc.createAnswer();
await pc.setLocalDescription(answer);
ws.send(JSON.stringify({ action: "answer", data: pc.localDescription, target: currentTarget, from: myKey }));
}
websocket

Code: Select all

function connectWebSocket() {
ws = new WebSocket(wsUrl);
ws.onopen = () => {
document.getElementById("status").textContent = "✅ متصل بالخادم";
registerUser();
};

ws.onmessage = async (ev) => {
const msg = JSON.parse(ev.data);
switch (msg.action) {
case "registered":
break;
case "user-list":
renderUsers(msg.users);
break;
case "all-users":
renderMapUsers(msg.users);
break;
case "offer":
await handleOffer(msg);
break;
case "answer":
await pc.setRemoteDescription(msg.data);
for (const c of pendingCandidates) await pc.addIceCandidate(c);
pendingCandidates = [];
break;
case "ice":
if (pc &&  pc.remoteDescription)
await pc.addIceCandidate(msg.data);
else pendingCandidates.push(msg.data);
break;
case "user-info":
renderSearchResults([msg.data]);
break;
case "search-results":
renderSearchResults(msg.users);
break;
}
};

ws.onclose = () => {
document.getElementById("status").textContent = "❌ غير متصل";
setTimeout(() => {
if (sessionStorage.getItem("userData")) connectWebSocket();
}, 3000);
};
}

async function registerUser() {
const location = await getGeo();
ws.send(JSON.stringify({ action: "register", name: myName, phone: myPhone, room: myRoom, location }));
}
Signalisierungsserver auf Python

Code: Select all

import asyncio
import json
import os
import time
import websockets

# -----------------------------
# In-memory state
# -----------------------------
# USERS_BY_KEY: key -> { name, phone, room, ip, location, ws, last_seen }
USERS_BY_KEY = {}
# WS_TO_KEY: ws -> key
WS_TO_KEY = {}

DATA_DIR = os.path.abspath(".")  # where we store per-user friends_*.json

def user_key_from(name: str, phone: str) -> str:
k = (phone or name or "").strip().lower()
return k

def friends_file_for(key: str) ->  str:
safe = "".join(ch for ch in key if ch.isalnum() or ch in ("_", "-", "."))
return os.path.join(DATA_DIR, f"friends_{safe}.json")

def load_friends(key: str):
path = friends_file_for(key)
if not os.path.exists(path):
return []
try:
with open(path, "r", encoding="utf-8") as f:
data = json.load(f)
if isinstance(data, list):
# normalize to lowercase unique strings
seen, out = set(), []
for x in data:
t = (x or "").strip().lower()
if t and t not in seen:
seen.add(t)
out.append(t)
return out
except Exception:
pass
return []

def save_friends(key: str, friends_list):
# normalize and persist
seen, out = set(), []
for x in friends_list:
t = (x or "").strip().lower()
if t and t not in seen:
seen.add(t)
out.append(t)
path = friends_file_for(key)
with open(path, "w", encoding="utf-8") as f:
json.dump(out, f, ensure_ascii=False, indent=2)
return out

async def broadcast_user_list(room: str):
"""Send the list of online users in 'room' to everyone in that room."""
users_payload = []
now = time.time()
for key, info in USERS_BY_KEY.items():
if info.get("room") == room and info.get("ws") is not None:
users_payload.append({
"name": info.get("name"),
"phone": info.get("phone"),
"ip": info.get("ip"),
"room": info.get("room"),
"location": info.get("location"),
"last_seen": info.get("last_seen", now),
})
msg = json.dumps({"action": "user-list", "users": users_payload})
tasks = []
for key, info in USERS_BY_KEY.items():
if info.get("room") == room and info.get("ws") is not None:
tasks.append(info["ws"].send(msg))
if tasks:
await asyncio.gather(*tasks, return_exceptions=True)

async def handle_register(ws, data):
name = (data.get("name") or "").strip()
phone = (data.get("phone") or "").strip()
room = (data.get("room") or "main").strip() or "main"
location = data.get("location")  # {lat, lon} or None

key = user_key_from(name, phone)
if not key:
await ws.send(json.dumps({"action": "error", "error": "Missing name/phone"}))
return

ip = ws.remote_address[0] if ws.remote_address else "unknown"

USERS_BY_KEY[key] = {
"name": name,
"phone": phone,
"room": room,
"ip": ip,
"location": location,
"ws": ws,
"last_seen": time.time(),
}
WS_TO_KEY[ws] = key

await ws.send(json.dumps({"action": "registered", "key": key, "ip": ip, "room": room}))
await broadcast_user_list(room)

async def handle_get_friends(ws):
key = WS_TO_KEY.get(ws)
if not key:
await ws.send(json.dumps({"action": "friends", "friends": []}))
return
friends = load_friends(key)
await ws.send(json.dumps({"action": "friends", "friends": friends}))

async def handle_friend_add(ws, data):
key = WS_TO_KEY.get(ws)
if not key:
return
target = (data.get("target") or "").strip().lower()
if not target:
return
current = load_friends(key)
if target not in current:
current.append(target)
current = save_friends(key, current)
await ws.send(json.dumps({"action": "friends", "friends": current, "ok":  True}))

async def handle_friend_remove(ws, data):
key = WS_TO_KEY.get(ws)
if not key:
return
target = (data.get("target") or "").strip().lower()
if not target:
return
current = load_friends(key)
current = [x for x in current if x != target]
current = save_friends(key, current)
await ws.send(json.dumps({"action": "friends", "friends": current, "ok": True}))

async def handler(ws):
print("🌐 Client connected")
try:
async for raw in ws:
try:
data = json.loads(raw)
except json.JSONDecodeError:
continue
act = data.get("action")

if act == "register":
await handle_register(ws, data)

elif act == "get-friends":
await handle_get_friends(ws)

elif act == "friend-add":
await handle_friend_add(ws, data)

elif act == "friend-remove":
await handle_friend_remove(ws, data)

elif act == "get-all-users":
# Optional: send all users (for map/debug)
payload = []
for key, info in USERS_BY_KEY.items():
payload.append({
"name": info.get("name"),
"phone": info.get("phone"),
"room": info.get("room"),
"ip": info.get("ip"),
"location": info.get("location"),
"last_seen": info.get("last_seen", time.time()),
})
await ws.send(json.dumps({"action": "all-users", "users": payload}))
elif act == "chat":
sender_key = WS_TO_KEY.get(ws)
if not sender_key:
continue
text = (data.get("text") or "").strip()
room = USERS_BY_KEY.get(sender_key, {}).get("room", "main")
if not text:
continue
msg = json.dumps({
"action": "chat",
"from": sender_key,
"text": text,
"time": time.strftime("%H:%M:%S"),
})
# broadcast to same room
tasks = []
for key, info in USERS_BY_KEY.items():
if info.get("room") == room and info.get("ws"):
tasks.append(info["ws"].send(msg))
if tasks:
await asyncio.gather(*tasks, return_exceptions=True)

elif act == "chat-private":
sender_key = WS_TO_KEY.get(ws)
target_key = (data.get("target") or "").strip().lower()
text = (data.get("text") or "").strip()
if not sender_key or not target_key or not text:
continue
payload = json.dumps({
"action": "chat-private",
"from": sender_key,
"to": target_key,
"text": text,
"time":  time.strftime("%H:%M:%S"),
})
for k, info in USERS_BY_KEY.items():
if k in (sender_key, target_key) and info.get("ws"):
await info["ws"].send(payload)

except websockets.exceptions.ConnectionClosed:
pass
finally:
# cleanup
key = WS_TO_KEY.pop(ws, None)
if key and key in USERS_BY_KEY:
room = USERS_BY_KEY[key].get("room", "main")
USERS_BY_KEY[key]["ws"] = None
USERS_BY_KEY[key]["last_seen"] = time.time()
print(f"❎ {key} disconnected")
await broadcast_user_list(room)

async def main():
host = "0.0.0.0"
port = 8555
print("📂 Data dir:", DATA_DIR)
print(f"📡 Signaling server on ws://{host}:{port}")
async with websockets.serve(handler, host, port, ping_interval=20, ping_timeout=20):
await asyncio.Future()

if __name__ == "__main__":
asyncio.run(main())

Quick Reply

Change Text Case: 
   
  • Similar Topics
    Replies
    Views
    Last post