简体   繁体   中英

How to correctly send image through socket using python client and C server

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 (eg 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.

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).

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM