0

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.

4
  • Unrelated: send_message looks like it has the potential to hold the mutex locked for an uncomfortably long time. Commented Dec 7, 2020 at 17:26
  • Never ignore the return codes from, well anything, but you can't ignore them in socket programming. For example, 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. Commented Dec 7, 2020 at 17:31
  • 1
    Socket code, 'image' and 'strlen' in the same post:(( Commented Dec 7, 2020 at 18:30
  • How do you determine if the recieved data is a text message or binary image data? You should consider creating a more robust custom protocol that sends a value in the first byte that indicates how to treat the rest of the data. You also need to be careful about null bytes. A byte with value 0x00 in a string data means the end of the string whereas the same byte in image data just represents a black pixel. Commented Dec 7, 2020 at 18:53

1 Answer 1

4

Socket rx/tx functions normally return the actual number of bytes transmitted. Thus the proper way of doing the rx/tx is to call the function in a loop, while accumulating return value and moving the buffer start pointer. Moreover, when dealing with binary data - such as image data - null termination assumption is wrong and truncates the data in wrong length; it may also trigger array index out-of-bounds related exceptions. You need to explicitly specify rx/tx byte count (strlen is wrong).

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.