I am programming chat-like application in which user apart from sending messages can also send pictures. Only problem is that I am not sure how should I approach image sending. Main idea is that user chooses image writing /send image.jpg in the console, and then image is sent via socket.send(image.jpg). Sending image works fine for me, but my C server is getting data input from client in seperate "packages" because of buffor, but when I add them, they don't match the size of my image (e.g. my image is 73kb but server gets 29kb from two separate "packages" 20kb + 8.5kb). And the second problem is how to send this data further, I thought that maybe there is some way of passing buffor with actual image binary data and send it to the rest of my clients in Python.
My buffer is 20480 bytes.
Sending from client.py:
elif "/send " in buffer:
fileArr = buffer.split(' ') #filearr = ["/send", "image.jpg"]
file = open(fileArr[1], "rb").read()
s.send(fileArr[0].encode()) #metadata that im sending image file
time.sleep(0.2)
s.send(file) #sending my file
time.sleep(1)
print("Image sent!")
My server.c receiving and sending:
void send_message(char *s, int uid){
pthread_mutex_lock(&clients_mutex);
for (size_t i = 0; i < MAX_CLIENTS; i++) {
if(clients[i]){
if(clients[i]-> uid != uid){
if(write(clients[i]->sockfd, s, strlen(s)) < 0){
perror("");
printf("Write to descriptor failed \n");
break;
}
}
}
}
pthread_mutex_unlock(&clients_mutex);
}
if(strstr(buffer, "/send") != NULL || receive > 128){
if(strstr(buffer, "/send")){
buffer[0] = '\0';
}
recv(cli->sockfd, buffer, sizeof(buffer), 0); // Receiving my image and saving it to buffer
printf("receiveing img");
send_message(buffer, cli->uid); // Sending my buffer further to client
printf("sending image\n" );
And my client.py receiving:
def recvDataLoop():
while True:
reply = s.recv(buffer_sz)
if reply:
print("Got reply");
flag = 0
try:
reply = reply.decode()
if flag != 1 and "joined the chat" in reply or "has left" in reply:
print(reply)
elif flag != 1 and "|" in reply:
replyArr = reply.split("|")
time.sleep(0.1)
print("{}: {}".format(replyArr[0],replyArr[1]))
except:
print("Encoded") #If data received and it cannot be decoded, its <bytes>
try:
f = open("cat4.jpg", "ab").write(reply) #If image exists, write data to existing image
except:
f = open("cat4.jpg", "wb").write(reply)
I needed to make this try-except blocks because that when data is received, it's received in packages so when I get it, I need to write it to the end of my cat4.jpg file.
send_messagelooks like it has the potential to hold the mutex locked for an uncomfortably long time.recv's return code tell you how much data was read. This is vital information because you never really know just how much data you're going to get.0x00in a string data means the end of the string whereas the same byte in image data just represents a black pixel.