I am trying to code a kind of video chat room, like video conference call. I'm trying to do this with UDP, so that I won't have much lags. However, I can't send large enough sizes, even though I'm using all pickle, json and struct to make the size smaller.
The error I get:
socket.error: [Errno 10040] A message sent on a datagram socket was larger than the internal message buffer or some other network limit, or the buffer used to receive a datagram into was smaller than the datagram itself
How can I make my code work (any ideas would be great, just how to make a conference video call with the less amount of lags possible).
Thanks in advance!
EDIT: I already have a text chatroom in UDP, what I'm trying to do now is extend it to also be voice chat room and video chat room. I have problems in the video, as I mentioned! Thanks!
Code:
Server:
__author__ = 'user'
import socket
import time
import sys
import json
import pickle
import numpy as np
import struct
UDP_IP = sys.argv[1]
UDP_PORT = int(sys.argv[2])
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP,UDP_PORT))
clients = []
def broadcast(data):
global clients
for client in clients:
sock.sendto(data, client[1])
while True:
data = None
message = None
try:
sock.settimeout(0.01)
data, addr = sock.recvfrom(1024)
message = json.loads(data)
client = (message['username'], addr)
if client not in clients:
clients.append(client)
except socket.error:
time.sleep(0.01)
if data:
print data
try:
if (message['message'].startswith("/hello")):
to_send = {"username" : "server", "message" : message['username'] + " joined the chat"}
to_send_final = json.dumps(to_send)
broadcast(to_send_final)
elif (message['message'].startswith("/who")):
to_send = {"username" : "server","message" : "people in room: " + ', '.join([y[0] for y in clients])}
to_send_final = json.dumps(to_send)
sock.sendto(to_send_final, client[1])
elif (message['message'].startswith("/goodbye")):
to_send = {"username" : "server", "message" : message['username'] + " left the chat"}
to_send_final = json.dumps(to_send)
clients.remove(client)
broadcast(to_send_final)
else:
to_send = {"username" : message['username'],"message" : message['message']}
to_send_final = json.dumps(to_send)
broadcast(to_send_final)
print clients
except:
print "an error has occured"
Client:
__author__ = 'user'
import socket
import sys
import thread
import time
import json
import cv2
import numpy as np
import pickle
import struct
server_ip = sys.argv[1]
server_port = sys.argv[2]
username = sys.argv[3]
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
cap=cv2.VideoCapture(0)
def get_messages():
global sock, username
data_2 = ""
payload_size = struct.calcsize("L")
while True:
while len(data) < payload_size:
data += sock.recv(4096)
packed_msg_size = data[:payload_size]
data = data[payload_size:]
msg_size = struct.unpack("L", packed_msg_size)[0]
while len(data) < msg_size:
data += sock.recv(4096)
frame_data = data[:msg_size]
data = data[msg_size:]
frame=pickle.loads(frame_data)
print frame
cv2.imshow('frame',frame)
if cv2.waitKey(1) & 0xFF == ord('q'):
break
def get_input():
global sock, username
try:
while True:
ret,frame=cap.read()
vid_message = pickle.dumps(frame)
message = { "username" : username, "message" : vid_message }
final_message = json.dumps(message)
last_message = struct.pack("L", len(final_message))+final_message
sock.sendto(last_message, (server_ip, int(server_port)))
except KeyboardInterrupt:
print "byebye now"
thread.start_new_thread(get_input, ())
thread.start_new_thread(get_messages, ())
message = {"username" : username, "message" : "/hello"}
sock.sendto(json.dumps(message), (server_ip, int(server_port)))
message = {"username" : username, "message" : "/who"}
sock.sendto(json.dumps(message), (server_ip, int(server_port)))
try:
while 1:
time.sleep(0.01)
except KeyboardInterrupt:
print "bye"
message = {"username" : username, "message" : "/goodbye"}
sock.sendto(json.dumps(message), (server_ip, int(server_port)))
sock.close()
cap.release()
cv2.destroyAllWindows()
sys.exit(0)
By the way, the basis of that code is not mine, i found it on the internet and changed it to my needs. Basically, the server streams the data to all of the clients every times he recieves data from one of them. Thanks for any help!