C - 使用tcp连接的简单加密套接字无法加密大文件

时间:2016-01-13 20:48:07

标签: c sockets encryption tcp

它使用阻塞队列来加密带有XOR的文件。

缓冲区设置得非常大,但是当我加密大文件(1000个字符或更多)的加密时,我应该收到相同的文件,但我只接收开头。谁知道如何解决这个问题? 感谢。

    #include <stdio.h>
#include <stdlib.h>
#include <dirent.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <fcntl.h>
#include <time.h>
#include <assert.h>
#include <errno.h>
#include <string.h>
#include <pthread.h>
#include <signal.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/select.h>
#include <netinet/tcp.h>
#include "os_queue.c"


#define BACKLOGGED_CONNECTIONS 10

queue_t new_queue;
int i=0;


void *worker_thread(void* key_path) {
    int j = i;
    i++;
    printf("worker %d stssssart\n",j);
    int rc;
    int sockfd;
    int key_fd;
    if ((key_fd = open(key_path, O_RDONLY)) < 0) {
        printf("ERROR: open key file failed: %s\n",strerror(errno));
        exit(1);
    }
    while (1) {

        rc = queue_dequeue(&new_queue,&sockfd);

        if (rc != 0) {
            printf("error! dequeue of a client's sockfd from the shared queue failed: %d\n",rc);
        }

        if(cipher(sockfd,key_fd)!=0){
            printf("chipher did not work");
            exit(1);
        }
    }
    printf("worker %d finish\n",j);

    close(key_fd);
    pthread_exit((void*) &key_fd);

}

int cipher(int sockfd,int key_fd){
    int keyFileFD, numberOfBytes,loop,n,key_num,totalsent,nsent,i;
    char inputBuffer[262144], keyBuffer[262144],outputBuffer[262144];

    if(lseek(key_fd,0,SEEK_SET) == -1){
        printf("lseek function failed %s\n", strerror(errno));
        return errno;
    }

    while (1) {
        n = read(sockfd, inputBuffer, sizeof(inputBuffer));
        if(n < 0){

            if(errno ==EPIPE || errno == ENOTCONN || errno == ECONNRESET) {
                printf("111");
                close(sockfd);
                return 0;
            }
            else{
                printf("Read error: %s\n", strerror(errno));
                close(sockfd);
                return 0;
            } 

        }
        key_num=read(key_fd, keyBuffer, n);
        if (key_num < 0) {

            printf("Error reading file: %s\n", strerror(errno));
            return errno;
            }

            while (key_num<n) {
                if(lseek(key_fd,0,SEEK_SET) == -1) {
                        /*
                        *error
                        */
                        printf("lseek function failed %s\n", strerror(errno));
                        return errno;
                }

                int cont=read(key_fd, keyBuffer+key_num, n-key_num);
                if (cont == -1) {
                    printf("Error reading  file: %s\n", strerror(errno));
                    return errno;
                }
                key_num=key_num+cont;
            }


            for(i=0;i<n;i++){

                outputBuffer[i] = (inputBuffer[i] ^ keyBuffer[i]);                                              
            }

            if(write(sockfd, outputBuffer,n)<0) {
                if(errno ==EPIPE || errno == ENOTCONN || errno == ECONNRESET) {
                    close(sockfd);
                    return 0;
                } else{
                    printf("Read error: %s\n", strerror(errno));
                    close(sockfd);
                    return 0;
                } 



            }
            close(sockfd);
        }

    return 0;
    }


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

    int base_sockfd, new_sockfd,i, rc, keyFileFD, num_of_workers,addrsize_1,addrsize_2;
    struct sockaddr_in serv_addr, client_addr;
    char* key_path = argv[3];
    addrsize_1 = sizeof(struct sockaddr);
    num_of_workers = atoi(argv[1]);

    if(argc!=4){
        printf("number of args is not 4: %s\n",strerror(errno));
        return errno;
    }

    if(access(key_path, R_OK)<0){
        printf("Key file does not exist or the file is not accessible: %s\n",strerror(errno));
        return errno;
    }

    /*init data structures*/
    rc = init_queue(&new_queue,2*num_of_workers);
    if (rc!=0) {
        printf("error! shared queue init failed\n");
        return 1;
    }

    pthread_t threads[num_of_workers];


    /*create workers*/
    for (i = 0; i < num_of_workers; i++) {
        rc = pthread_create(&threads[i], NULL, worker_thread,  (void*) key_path);
        if (rc != 0) {
            printf("error! pthread_create() failed: %d\n", rc);
            return 1;
        }
    }

    memset(&serv_addr, '0', sizeof(serv_addr));
    serv_addr.sin_family = AF_INET;
    serv_addr.sin_port = htons(atoi(argv[2])); // short, network byte order
    serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");//INADDR_ANY;


    if ((base_sockfd = socket(PF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("error! socket() failed: %s\n", strerror(errno));
        return errno;
    }

    if (bind(base_sockfd, (struct sockaddr *)&serv_addr, addrsize_1) < 0) {
        printf("error! bind() failed: %s\n", strerror(errno));
        close(base_sockfd);
        return errno;
    }

    addrsize_2 = sizeof(struct sockaddr_in);

    if (listen(base_sockfd,SOMAXCONN) < 0) {
        printf("error! listen() failed: %s\n", strerror(errno));
        return errno;
    }



        while(1){
        if ( (new_sockfd = accept(base_sockfd, (struct sockaddr*)&client_addr, &addrsize_2)) <= 0) {
            printf("error! accept() failed: %s\n", strerror(errno));
            close(base_sockfd);
            return errno;
        }
        /*we have a new valid client sockfd, so enqueue it*/
        rc = queue_enqueue(&new_queue, new_sockfd);
        if (rc!= 0) {
            printf("error! enqueue to shared queue failed withe value:%d\n",rc);
            return 1;
        }

        }
    /*clean up and close resources*/
    rc=free_queue(&new_queue);
        if(rc!=0)
        printf("error! free queue failed with value:%d\n",rc);
        return 1;
    //close(base_sockfd);
    /*exit gracefully*/

}

队列:

#include <pthread.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>



typedef struct queue {
    int *arr;
    int capacity;
    int size;
    int in;
    int out;
    pthread_mutex_t mutex;
    pthread_cond_t cond_full;
    pthread_cond_t cond_empty;
} queue_t;


int queue_enqueue(queue_t *queue, int value) {
    int rc;
    rc = pthread_mutex_lock(&(queue->mutex));
    if(rc!=0){
        return rc;
    }
    while (queue->size == queue->capacity) {
        pthread_cond_wait(&(queue->cond_full), &(queue->mutex));
    }
    queue->arr[queue->in] = value;
    ++ queue->size;
    ++ queue->in;
    queue->in %= queue->capacity;
    rc = pthread_mutex_unlock(&(queue->mutex));
    if(rc!=0){
        return rc;
    }
    rc = pthread_cond_signal(&(queue->cond_empty));
    if(rc!=0){
      return rc;
    }
}

int queue_dequeue(queue_t *queue,int *value){
    int rc;
    rc = pthread_mutex_lock(&(queue->mutex));
    if(rc!=0){
      return rc;
    }
    while (queue->size == 0){
        pthread_cond_wait(&(queue->cond_empty), &(queue->mutex));
    }
    *value = queue->arr[queue->out];
    -- queue->size;
    ++ queue->out;
    queue->out %= queue->capacity;
    rc = pthread_mutex_unlock(&(queue->mutex));
    if(rc!=0){
        return rc;
    }
    rc = pthread_cond_signal(&(queue->cond_full));
    return rc;

}



int init_queue(queue_t *new_queue,int cnt) {
    int rc;
    new_queue->capacity = cnt;
    new_queue->arr = malloc(sizeof(cnt)*sizeof(int));
    if (new_queue->arr== NULL) {
      return -1;
    }
    new_queue->size = 0;
    new_queue->in = 0;
    new_queue->out = 0;
    //init shared queue lock (mutex)
    rc =  pthread_mutex_init(&(new_queue->mutex), NULL);
    if (rc != 0) {
        return rc;
    }

    //init shared queue conditions variable
    rc = pthread_cond_init(&(new_queue->cond_full), NULL); 
    if (rc != 0) {
        return rc;
    }
    rc = pthread_cond_init(&(new_queue->cond_empty), NULL); 
    if (rc != 0) {
        return rc;
    }
}

int free_queue(queue_t *queue_to_kill) {
    int rc;
    rc = pthread_mutex_destroy(&(queue_to_kill->mutex));
    if (rc) {
        return rc;
    }
    rc = pthread_cond_destroy(&(queue_to_kill->cond_empty));
        if (rc) {
        return rc;
    }
    rc = pthread_cond_destroy(&(queue_to_kill->cond_full));
    if (rc) {
        return rc;
    }
}

客户端:

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <ctype.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <unistd.h>
#include <fcntl.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <pthread.h>

int connectToHostname(int sock, char* hostname, char* port);
int main(int argc, char* argv[]){
    int sock;
        char* hostname;
        char* port;


        /* place default port if required*/
        if(argc < 3)
        {
            port = "42666";
        }
        else
        {
            port = argv[2];
        }
        /* place default hostname if required*/
        if(argc == 1)
        {
            hostname = "localhost";
        }
        else
        {
            hostname = argv[1];
        }

        /* open TCP socket with IPv4*/
        if((sock = socket(PF_INET, SOCK_STREAM, 0))<0)
        {
            perror("Could not open socket");
            exit(errno);
        }
        int fd = -1;
        int fd2 = -1;
        if(argc >= 4)
        {
             fd = open(argv[3], O_WRONLY|O_CREAT|O_TRUNC, 0666);
        }
        if(argc >= 5)
        {
            fd2 = open(argv[4], O_RDONLY, 0);
        }
        connectToHostname(sock, hostname, port);
        char buf[100];
        while(1)
        {
            if(fd2 <0)
            {
                scanf("%99s",buf);
                send(sock, buf, strlen(buf), 0);
            }
            else
            {
                int stupid = read(fd2, buf, 99);
                if(stupid == 0)
                {
                    close(sock);
                    exit(0);
                }
                send(sock, buf, stupid, 0);
            }

            int sz = recv(sock, buf, 99, 0);
            buf[100] = '\0';
            if(fd< 0)
                {
                printf("%s\n", buf);
                }
            else
            {
                write(fd, buf, sz);
            }
        }
}
int connectToHostname(int sock, char* hostname, char* port)
{
    int rv;
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_in *h;
    struct sockaddr_in dest_addr;

    /* server addr is IPv4*/
    dest_addr.sin_family = AF_INET;
    /* write server port*/
    dest_addr.sin_port = htons((short)strtol(port, NULL,10));
    /* zero out hints (since garbage is bad)*/
    memset(&hints, 0, sizeof(hints));
    /* we want IPv4 address and TCP*/
    hints.ai_family = AF_INET;
    hints.ai_socktype = SOCK_STREAM;
    /* try get address info*/
    if((rv = getaddrinfo(hostname, port, &hints, &servinfo)) != 0)
    {
        fprintf(stderr, "Error getting address info: %s\n", gai_strerror(rv));
        exit(1);
    }
    p = servinfo;
    while(p!= NULL)
    {
        /* put last address into sent pointer*/
        h = (struct sockaddr_in *)p->ai_addr;
        dest_addr.sin_addr = h->sin_addr;
        if(connect(sock, (struct sockaddr*)(&dest_addr), sizeof(struct sockaddr)) == 0)
                break;/* if connection succesfull*/
        p = p->ai_next;
    }
    freeaddrinfo(servinfo);
    if(p == NULL)
    {
        /*We didnt find a host*/
        perror("Could not connect to server");
        exit(errno);
    }
    return 0;
}

我用这个脚本来测试它:

echo niv > key_file
echo is > read_file_b
echo thethethethethethethethethethe > read_file_c
echo se > read_file_d
echo rse > read_file_e
echo rse > read_file_f

echo aaaaaaa > write_file_a
echo bbbbbbb > write_file_b
echo ccccccc > write_file_c
echo ddddddd > write_file_d
echo ddddddd > write_file_e
echo ddddddd > write_file_f

gcc setos_server.c -pthread -o setos_server
./setos_server 3 2 key_file &
sleep 0.1
#printf "\n\n"
gcc client.c -pthread -o client
./client 127.0.0.1 2 write_file_a read_file_a &
./client 127.0.0.1 2 write_file_b read_file_b &
./client 127.0.0.1 2 write_file_c read_file_c &
./client 127.0.0.1 2 write_file_d read_file_d &
./client 127.0.0.1 2 write_file_e read_file_e &
./client 127.0.0.1 2 write_file_f read_file_f &


./client 127.0.0.1 2 final_file_a write_file_a &
./client 127.0.0.1 2 final_file_b write_file_b &
./client 127.0.0.1 2 final_file_c write_file_c &
./client 127.0.0.1 2 final_file_d write_file_d &
./client 127.0.0.1 2 final_file_e write_file_e &
./client 127.0.0.1 2 final_file_f write_file_f &

sleep 2

pkill setos_server

当read_file_a是一个大文件(超过10000个字符)时。

谢谢你的帮助。

1 个答案:

答案 0 :(得分:2)

太多close()

while (1) {
    n = read(sockfd, inputBuffer, sizeof(inputBuffer));
    if(n < 0){
        ....
    }
    close(sockfd);
}

在第一个read()之后杀死套接字。

PS:更短的功能和正确的格式化使得它很容易被发现。