我想在单个客户端服务器连接上发送多个文件。服务器应接受来自客户端的连接,然后循环访问文件夹并将其中的每个文件发送到客户端。有什么好方法可以让客户端在收到文件后保存每个文件然后正确读取下一个文件。
我有以下服务器代码,只发送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 :(得分:0)
这就是我提出的,如果有人有任何建设性的批评,我很乐意听到。使用python客户端工作得很好我写了10bytes(filesize),50bytes(文件名)和filesize字节(filedata)。
/*
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