我正在尝试使用线程编写文件传输程序。我想要遵循的格式是:
./server 4501 ..................(will run forever)
./client 4501 add1.txt
./client 4501 bdd1.txt
add1.txt和bdd1.txt将在服务器端保存为add2.txt和bdd2.txt。但是在运行我的代码后,我发现add2.txt包含add1.txt中的字符以及一些额外的字符。
**
**
服务器代码:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <unistd.h>
/* Preprocessor Directives */
#define NTHREADS 50
#define QUEUE_SIZE 5
#define BUFFER_SIZE 256
/* Global counter locked via mutex */
pthread_t threadid[NTHREADS]; // Thread pool
pthread_mutex_t lock;
int counter = 0;
void *threadworker(void *arg)
{
int sockfd, rw; // File descriptor and 'read/write' to socket indicator
char *buffer; // Message buffer
sockfd = (int) arg; // Getting sockfd from void arg passed in
buffer = malloc(BUFFER_SIZE);
bzero(buffer, BUFFER_SIZE);
rw = read(sockfd, buffer, BUFFER_SIZE); // Blocks until there is something to be read in the socket
FILE *fp;
fp=fopen("add2.txt","w");
fprintf(fp,"%s",buffer);
//fwrite(buffer, strlen(buffer) + 1, 1, fp);
//fwrite(buffer,sizeof(char),BUFFER_SIZE, fp);
fclose(fp);
printf("%d\n",strlen(buffer));
printf("the file was received successfully\n");
printf("the new file created is add2.txt\n");
if (rw < 0)
{
perror("Error reading form socket, exiting thread");
pthread_exit(0);
}
//printf("New message received: %s", buffer); // String already has newline
bzero(buffer, BUFFER_SIZE);
//sprintf(buffer, "Acknowledgement from TID:0x%x", pthread_self());
/*rw = write(sockfd, buffer, strlen(buffer));
if (rw < 0)
{
perror("Error writing to socket, exiting thread");
pthread_exit(0);
}*/
/* Critical section */
/*printf("Requesting mutex lock...\n");
pthread_mutex_lock (&lock);
printf("Current counter value: %d, upping by 1...\n", counter);
counter++;
pthread_mutex_unlock (&lock);
printf("Done! Mutex unlocked again, new counter value: %d\n", counter);
*/
close(sockfd);
//printf("TID:0x%x served request, exiting thread\n", pthread_self());
pthread_exit(0);
}
int main(int argc, char *argv[])
{
/* Variable declarations */
int serv_sockfd, new_sockfd; //Socket identifiers for server and incoming clients
struct addrinfo flags; // Params used to establish listening socket
struct addrinfo *host_info; // Resultset for localhost address info, set by getaddrinfo()
socklen_t addr_size; // Client address size since we use sockaddr_storage struct to store
// client info coming in, not using addrinfo as done for host (local)
// by calling getaddrinfo for resolution, which stores results in
// the more convenient addrinfo struct
struct sockaddr_storage client; // Sockaddr storage struct is larger than sockaddr_in,
// can be used both for IPv4 and IPv6
pthread_attr_t attr; // Thread attribute
int i; // Thread iterator
/* Start of main program */
if (argc < 2) {
fprintf(stderr,"Error: no port provided\n");
exit(-1);
}
memset(&flags, 0, sizeof(flags));
flags.ai_family = AF_UNSPEC; // Use IPv4 or IPv6, whichever
flags.ai_socktype = SOCK_STREAM; // TCP
flags.ai_flags = AI_PASSIVE; // Set address for me
if (getaddrinfo(NULL, argv[1], &flags, &host_info) < 0)
{
perror("Couldn't read host info for socket start");
exit(-1);
}
serv_sockfd = socket(host_info->ai_family, host_info->ai_socktype, host_info->ai_protocol);
if (serv_sockfd < 0)
{
perror("Error opening socket");
exit(-1);
}
if (bind(serv_sockfd, host_info->ai_addr, host_info->ai_addrlen) < 0)
{
perror("Error on binding");
exit(-1);
}
freeaddrinfo(host_info); // Don't need this struct anymore
pthread_attr_init(&attr); // Creating thread attributes
pthread_attr_setschedpolicy(&attr, SCHED_FIFO); // FIFO scheduling for threads
pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED); // Don't want threads (particualrly main)
// waiting on each other
listen(serv_sockfd, QUEUE_SIZE); // Pass in socket file descriptor and the size of the backlog queue
// (how many pending connections can be in queue while another request
// is handled)
addr_size = sizeof(client);
i = 0;
while (1)
{
if (i == NTHREADS) // So that we don't access a thread out of bounds of the thread pool
{
i = 0;
}
new_sockfd = accept(serv_sockfd, (struct sockaddr *) &client, &addr_size);
if (new_sockfd < 0)
{
perror("Error on accept");
exit(-1);
}
pthread_create(&threadid[i++], &attr, &threadworker, (void *) new_sockfd);
sleep(0); // Giving threads some CPU time
}
return 0;
}
客户代码为:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <netdb.h>
#include <netinet/in.h>
#include <pthread.h>
#include <unistd.h>
#define BUFFER_SIZE 256
int main(int argc, char *argv[])
{
int sockfd, rw;
struct addrinfo flags;
struct addrinfo *server_info;
char *buffer = malloc(BUFFER_SIZE);
if (argc < 4)
{
fprintf(stderr, "Usage: ./client <hostname/address> <port> <file_path>");
exit(-1);
}
memset(&flags, 0, sizeof(flags)); // Clear so we're not working with garbage
flags.ai_family = AF_UNSPEC; // IPv4 or IPv6 doesn't matter
flags.ai_socktype = SOCK_STREAM; // TCP
flags.ai_flags = AI_PASSIVE; // get the IP for me
if (getaddrinfo(argv[1], argv[2], &flags, &server_info) < 0) { // Resolve host based on CMD args
perror("Couldn't find host");
exit(-1);
}
sockfd = socket(server_info->ai_family, server_info->ai_socktype, server_info->ai_protocol); // Initialize socket
if (connect(sockfd, server_info->ai_addr, server_info->ai_addrlen) < 0)
{
perror("Couldn't conenct...");
exit(-1);
}
//printf("Connection established, please enter a message:\n");
bzero(buffer, BUFFER_SIZE);
//fgets(buffer, BUFFER_SIZE - 1, stdin);
//char buffer[100];
FILE *f;
size_t read=0;
if((f=fopen(argv[3],"r"))==NULL){
printf("Failed");
exit(-1);
}
//fseek(f, 0, SEEK_END);
//len = ftell(f);
//while (fgets(buffer, strlen(buffer), f) != NULL)
//fscanf(f,"%s",buffer);
//fread(buffer, strlen(buffer)+1, 1, f);
do{
read = fread(buffer,sizeof(char),BUFFER_SIZE-1, f);
if (read > 0) //if return value is > 0
{
buffer[BUFFER_SIZE]='\0';
rw = write(sockfd, buffer, strlen(buffer));
}
}
while(read == BUFFER_SIZE); //end when a read returned fewer items
fclose(f);
//write(sock, &len, sizeof(int));
//write(sock, buffer, len);
printf("the file was sent successfully");
//rw = write(sockfd, buffer, strlen(buffer)); // Sending the contents of the buffer - writes using socket file descriptor
if (rw < 0)
{
perror("Failed to send message");
exit(-1);
}
/*bzero(buffer, BUFFER_SIZE);
rw = read(sockfd, buffer, BUFFER_SIZE); // Read the ENTIRE buffer because we don't know stlen yet
if (rw < 0)
{
perror("Error reading from socket");
exit(-1);
}
printf("The message is: %s\n", buffer);
*/
close(sockfd);
return 0;
}
我的add1.txt文件包含
abcd
efgh
ijkl
mnop
add2.txt文件包含输出:
abcd
efgh
ijkl
mnop
############################################################################################################################################################################################################################################
任何人都可以告诉我当时需要的修改是什么。
提前谢谢你。
答案 0 :(得分:1)
完成读/写文件后,需要在File * fp(服务器代码)和File * f(客户端代码)上调用fclose。您确实关闭了客户端和服务器之间的连接,但是您没有关闭文件流,这可能是文件为空的原因。因此,在您调用fprintf(服务器代码)和fscanf(客户端代码)之后调用fclose是安全的。