2017-12-11 3 views
-3

1つのクライアントサーバー接続で複数のファイルを送信したいと思います。サーバーはクライアントからの接続を受け入れてから、フォルダーをループしてそこのすべてのファイルをクライアントに送信する必要があります。これを行う良い方法は、クライアントが各ファイルを受信した後に保存し、次のファイルを正しく読み取れるようにすることです。1つの接続クライアントサーバーで複数のファイルを送信するC

以下のサーバーコードが1つのファイルのみを送信して閉じます。

/* 
    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

質問は何ですか? –

+3

クライアントが2つのファイルを区別できるように、ファイルの開始と終了を定義する通信プロトコルを定義する必要があります。これは、ファイルを送信する前にファイルのサイズを送信するのと同じくらい単純かもしれません。 – user4581301

+0

@ JakeFreemanどのように複数のファイルを1つの接続で送信するためのサーバーコードを記述しますか? – bakalolo

答えて

0

誰もが建設的な批判が聞きたいのであれば、これは私が思いついたものです。私は10bytes(filesize)、50bytes(filename)とfilesizeバイト(filedata)を読み込むために書いたPythonクライアントでうまく動作します。

/* 
    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クライアント

# 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 
関連する問題