2017-12-11 6 views
-3

하나의 클라이언트 서버 연결에서 여러 파일을 보내고 싶습니다. 서버는 클라이언트와의 연결을 수락 한 다음 폴더를 반복하고 거기에있는 모든 파일을 클라이언트로 보내야합니다. 클라이언트가 각 파일을받은 후 저장하고 다음 파일을 올바르게 읽을 수 있도록이 작업을 수행하는 좋은 방법은 무엇입니까?하나의 연결 클라이언트 서버에서 여러 파일 보내기 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

클라이언트가 두 파일을 구분할 수 있도록 파일 시작 및 종료시기를 정의하는 통신 프로토콜을 정의해야합니다. 이것은 파일을 보내기 전에 파일 크기를 보내는 것처럼 간단 할 수 있습니다. – user4581301

+0

@ JakeFreeman 하나의 연결에 mutiple 파일을 보내는 서버 코드를 작성하는 방법은 무엇입니까? – bakalolo

답변

0

누군가 건설적인 비평을 듣고 싶다면 내가 생각해 낸 것입니다. 10bytes (filesize), 50bytes (filename) 및 filesize bytes (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; 
} 

파이썬 클라이언트

# 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 
관련 문제