2017-12-11 6 views
-3

Ich möchte mehrere Dateien auf einem einzelnen Client-Server verbinden. Der Server sollte eine Verbindung vom Client akzeptieren und dann einen Ordner durchlaufen und jede Datei dorthin zum Client senden. Was ist eine gute Möglichkeit, dies zu tun, damit der Client jede Datei speichern kann, nachdem sie sie erhalten hat, und dann die nächste Datei korrekt lesen.Senden mehrerer Dateien in einem Client-Server-Verbindung C

Ich habe den folgenden Server-Code, der nur 1 Datei sendet und schließt.

/* 
    Server side C/C++ program to demonstrate Socket programming 

    compile: 
     gcc serverFile.c -o serverFile 
    run: 
     ./serverFile 

    from http://www.geeksforgeeks.org/socket-programming-cc/ 
*/ 
#include <stdio.h> 
#include <sys/socket.h> 
#include <sys/stat.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <fcntl.h> 

#define PORT 8080 

int main(int argc, char const *argv[]) 
{ 


    char *file_path = "image.jpg"; 
    int input_file; 

    input_file = open(file_path, O_RDONLY); 
    if (input_file == -1) { 
     exit(EXIT_FAILURE); 
    } 


    int server_fd, new_socket, valread; 
    struct sockaddr_in address; 
    int opt = 1; 
    int addrlen = sizeof(address); 
    char buffer[1024] = {0}; 
    char *hello = "Hello from server"; 

    // Creating socket file descriptor. AF_INET is IPv4, SOCK_STREAM is tcp. 
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) 
    { 
     perror("socket failed"); 
     exit(EXIT_FAILURE); 
    } 

    //Set socket option (optional?). SOL_SOCKET is socket level argument. 
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, 
                &opt, sizeof(opt))) 
    { 
     perror("setsockopt"); 
     exit(EXIT_FAILURE); 
    } 
    address.sin_family = AF_INET; 
    address.sin_addr.s_addr = INADDR_ANY; 
    address.sin_port = htons(PORT); 

    // Forcefully attaching socket to the port 8080 
    if (bind(server_fd, (struct sockaddr *)&address, 
           sizeof(address))<0) 
    { 
     perror("bind failed"); 
     exit(EXIT_FAILURE); 
    } 
    // If you want to read multiple server connections. 
    //int x; 
    //for (x = 0; x < 3; x++){ 
    if (listen(server_fd, 3) < 0) 
    { 
     perror("listen"); 
     exit(EXIT_FAILURE); 
    } 
    if ((new_socket = accept(server_fd, (struct sockaddr *)&address, 
         (socklen_t*)&addrlen))<0) 
    { 
     perror("accept"); 
     exit(EXIT_FAILURE); 
    } 
    valread = read(new_socket , buffer, 1024); 
    printf("%s\n",buffer); 

    /*********************** read file and send it over socket ****************************/ 


    //unsigned char buffer[1000]; 
    while (1) { 
      // Read data into buffer. We may not have enough to fill up buffer, so we 
      // store how many bytes were actually read in bytes_read. 
      int bytes_read = read(input_file, buffer, sizeof(buffer)); 
      if (bytes_read == 0) // We're done reading from the file 
       break; 

      if (bytes_read < 0) { 
       // handle errors 
       printf("read error!\n"); 
      } 

      // You need a loop for the write, because not all of the data may be written 
      // in one call; write will return how many bytes were written. p keeps 
      // track of where in the buffer we are, while we decrement bytes_read 
      // to keep track of how many bytes are left to write. 
      void *p = buffer; 
      while (bytes_read > 0) { 
       int bytes_written = write(new_socket, p, bytes_read); 
       if (bytes_written <= 0) { 
        // handle errors 
       } 
       bytes_read -= bytes_written; 
       p += bytes_written; 
      } 
    } 

    /***************************************************************************************/ 

    //send(new_socket , hello , strlen(hello) , 0); 
    //printf("Hello message sent\n"); 

    close(new_socket); 
    close(server_fd); 
    //} 
    return 0; 
} 
+0

Was ist die Frage? –

+3

Sie müssen ein Kommunikationsprotokoll definieren, das definiert, wann eine Datei beginnt und endet, damit der Client zwei Dateien unterscheiden kann. Dies kann so einfach sein wie das Senden der Dateigröße vor dem Senden der Datei. – user4581301

+0

@JakeFreeman Wie schreibe ich einen Servercode, um mehrere Dateien in einer Verbindung zu senden? – bakalolo

Antwort

0

Das ist, was ich kam, wenn jemand konstruktive Kritik hätte gerne hören. Funktioniert gut mit Python-Client Ich schrieb 10 Bytes (Dateigröße), 50 Bytes (Dateiname) und Filesize Bytes (Filedata) zu lesen.

/* 
    Server side C/C++ program to demonstrate Socket programming 

    compile: 
     gcc serverMultipleFileV2.c -o serverMultipleFileV2 
    run: 
     ./serverMultipleFileV2 

    from http://www.geeksforgeeks.org/socket-programming-cc/ 
*/ 
#include <stdio.h> 
#include <sys/socket.h> 
#include <sys/stat.h> 
#include <stdlib.h> 
#include <netinet/in.h> 
#include <string.h> 
#include <fcntl.h> 
#include <unistd.h> 
#include <assert.h> 
#include <stddef.h> 
#include <dirent.h> 

#define PORT 8080 

int main(int argc, char const* argv[]) 
{ 

    int server_fd, new_socket, valread; 
    struct sockaddr_in address; 
    int opt = 1; 
    int addrlen = sizeof(address); 
    char buffer[1024] = { 0 }; 
    char* hello = "Hello from server"; 

    // Creating socket file descriptor. AF_INET is IPv4, SOCK_STREAM is tcp. 
    if ((server_fd = socket(AF_INET, SOCK_STREAM, 0)) == 0) { 
     perror("socket failed"); 
     exit(EXIT_FAILURE); 
    } 

    //Set socket option (optional?). SOL_SOCKET is socket level argument. 
    if (setsockopt(server_fd, SOL_SOCKET, SO_REUSEADDR | SO_REUSEPORT, 
      &opt, sizeof(opt))) { 
     perror("setsockopt"); 
     exit(EXIT_FAILURE); 
    } 
    address.sin_family = AF_INET; 
    address.sin_addr.s_addr = INADDR_ANY; 
    address.sin_port = htons(PORT); 

    // Forcefully attaching socket to the port 8080 
    if (bind(server_fd, (struct sockaddr*)&address, 
      sizeof(address)) 
     < 0) { 
     perror("bind failed"); 
     exit(EXIT_FAILURE); 
    } 

    if (listen(server_fd, 3) < 0) { 
     perror("listen"); 
     exit(EXIT_FAILURE); 
    } 
    if ((new_socket = accept(server_fd, (struct sockaddr*)&address, 
      (socklen_t*)&addrlen)) 
     < 0) { 
     perror("accept"); 
     exit(EXIT_FAILURE); 
    } 
    valread = read(new_socket, buffer, 1024); 
    printf("%s\n", buffer); 

    /*********************** read file and send it over socket *************************/ 

    DIR* dir; 
    struct dirent* ent; 

    if ((dir = opendir("images/")) == NULL) { 
     printf("Couldn't open directory"); 
     exit(EXIT_FAILURE); 
    } 

    // loop through folder and read /send all files. 
    while ((ent = readdir(dir)) != NULL) { 

     if (!strcmp(ent->d_name, ".")) { 
      continue; 
     } 

     if (!strcmp(ent->d_name, "..")) { 
      continue; 
     } 

     // get the filename e.g. [CAM1]image6-2017-12-13-21-32-24.jpg 
     char file_name[50]; 
     strncpy(file_name, ent->d_name, 49); 
     file_name[49] = '\0'; 

     // get the filepath e.g. images/[CAM1]image6-2017-12-13-21-32-24.jpg 
     char pathname[80]; 
     char * filename = "images/"; 
     strcpy(pathname, filename); 
     strcat(pathname, file_name); 

     printf("FILENAME: %s\n", file_name); 
     printf("PATHNAME: %s\n", pathname); 

     // open file for read 
     int input_file; 
     input_file = open(pathname, O_RDONLY); 
     if (input_file == -1) { 
      printf("Couldn't read file!\n"); 
      exit(EXIT_FAILURE); 
     } 

     /*********Send filesize over socket*****/ 
     // get filesize 
     struct stat st; 
     stat(pathname, &st); 
     long file_size = (long)st.st_size; 
     char fileSizeString[10]; 
     // convert file_size to string 
     const int n = snprintf(NULL, 0, "%lu", file_size); 
     assert(n > 0); 
     int c = snprintf(fileSizeString, n + 1, "%lu", file_size); 
     assert(fileSizeString[n] == '\0'); 
     assert(c == n); 
     printf("file size:%s\n", fileSizeString); 
     int bytes_written = write(new_socket, fileSizeString, sizeof(fileSizeString)); 

     /*********Send filename over socket*****/ 
     bytes_written = write(new_socket, file_name, sizeof(file_name)); 

     /*********Send filedata over socket*****/ 
     while (1) { 
      // Read data into buffer. We may not have enough to fill up buffer, so we 
      // store how many bytes were actually read in bytes_read. 
      int bytes_read = read(input_file, buffer, sizeof(buffer)); 
      if (bytes_read == 0) // We're done reading from the file 
       break; 

      if (bytes_read < 0) { 
       // handle errors 
       printf("read error!\n"); 
       exit(EXIT_FAILURE); 
      } 

      // You need a loop for the write, because not all of the data may be written 
      // in one call; write will return how many bytes were written. p keeps 
      // track of where in the buffer we are, while we decrement bytes_read 
      // to keep track of how many bytes are left to write. 
      void* p = buffer; 
      while (bytes_read > 0) { 
       int bytes_written = write(new_socket, p, bytes_read); 
       if (bytes_written <= 0) { 
        // handle errors 
       } 
       bytes_read -= bytes_written; 
       p += bytes_written; 
      } 

     } 

    } 
    closedir(dir); 
    close(new_socket); //close connection with specific client 
    close(server_fd); // close connection to stop listening 

    return 0; 
} 

Python Client

# Read header size and multiple file data over tcp socket 
#!/usr/bin/env python 

import socket 
import sys 
import string 

TCP_IP = '192.168.0.102' 
TCP_PORT = 8080 

MESSAGE = "Hello, bakalolo speaking" 

#f = open('torecv.jpg','wb') 

s = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 
s.connect((TCP_IP, TCP_PORT)) 
s.send(MESSAGE) 

while(True): 

    print "*************************************************" 

    # ----------Read file size (10 bytes) from socket----- 
    fileSizeRecievedCounter = 0 #store number of file size bytes read so far 
    fileSize = "" # store file size data as string when read 
    l = s.recv(10) 
    # if no more data left, all images should be read from server. 
    if len(l) == 0: 
     break 
    fileSizeRecievedCounter += len(l) #incriment bytes read counter 
    fileSize += l #concat read data to filename 
    # Keep reading until we have 10 bytes just in case 
    while(fileSizeRecievedCounter < 10): 
     l = s.recv(10 - fileSizeRecievedCounter) 
     fileSizeRecievedCounter += len(l) 
     fileSize += l 

    print "file sizeb4convert:", repr(l) 
    l = l.split('\0', 1)[0] 
    #l = filter(lambda x: x in string.printable, l) #remove byte values from string 
    fileSize = int(l) 
    print "file size:", repr(fileSize) 

    # ----------Read file name (50 bytes) from socket----- 
    fileNameRecievedCounter = 0 #store number of file name bytes read so far 
    fileName = "" 
    # read file name 
    l = s.recv(50) 
    fileNameRecievedCounter += len(l) #incriment bytes read counter 
    fileName += l #concat read data to filename 
    while(fileNameRecievedCounter < 50): 
     l = s.recv(50 - fileNameRecievedCounter) 
     fileNameRecievedCounter += len(l) 
     fileName += l 

    print "file nameb4convert:", repr(fileName) 
    fileName = fileName.split('\0', 1)[0] 
    #fileName = filter(lambda x: x in string.printable, l) 
    print "file name:", repr(fileName) 


    f = open(fileName,'wb') 
    # read file data 
    fileSizeRecieved = 0 #store number of bytes read so far 
    l = s.recv(1024) 
    f.write(l) 
    fileSizeRecieved += len(l) #add bytes read to counter 
    while (l): 

     if fileSizeRecieved == fileSize: 
      break 

     bytesLeft = fileSize - fileSizeRecieved 
     if bytesLeft < 1024: #if less than 1024 bytes left, read how much is left 
      l = s.recv(bytesLeft) 
      f.write(l) 
      fileSizeRecieved += len(l) 
     else: 
      l = s.recv(1024) 
      f.write(l) 
      #print "Receiving...", len(l) 
      fileSizeRecieved += len(l) 

    print "Done receiving! Total:", fileSizeRecieved 

f.close() 
s.close() 

#print "received data:", l 
Verwandte Themen