每当我释放结构时,C winsock程序崩溃

时间:2018-11-20 21:08:35

标签: c windows multithreading free winsock2

我知道这有点la脚,但是我的代码在做什么错呢?基本上,我想使用UDP在本地IP上创建通信,还发送一些文件等。问题是,当我在使用结构/将它们转换为char *之后释放结构时,程序崩溃了。更奇怪的是,在使用CLion调试器进行调试和逐步调试时,该程序不会崩溃。我究竟做错了什么?这是我的源代码:

当通过网络发送文件时无法分配更多内存(逻辑上,我需要释放一些内存)时,似乎发生了错误。发送消息就可以了

#define _WINSOCK_DEPRECATED_NO_WARNINGS
#define _CRT_SECURE_NO_WARNINGS
// PKS2Visual.cpp : Defines the entry point for the console application.
//

#include "main.h"

#include <stdio.h>
#include <string.h>
#include <winsock2.h>
#include <windows.h>
#include <time.h>

#define BREAKSOMETHING 0

#pragma comment(lib, "ws2_32.lib")

int fragSize = 1500;
int isInside = 0;
SOCKET s1, s2;
struct sockaddr_in server, myClient, otherClient;

int main() {
    char mode;
    printf("Enter fragment size:\n");
    scanf("%d", &fragSize);
    p2pMode();
}

DWORD WINAPI receiveThreadFunc(LPVOID lpParam) {
    int slen = sizeof(otherClient);
    int doRun = 1;
    int sizee;
    char msgBuffer[1519];
    char fileName[1519];
    int receivingFile = 0;
    while (doRun) {
        printf("Waiting for data...\n\n");
        if ((recvfrom(s1, msgBuffer, 1519, 0, (struct sockaddr *) &otherClient,
                      &slen)) == SOCKET_ERROR) {
            printf("recvfrom() failed with error code : %d\n", WSAGetLastError());
            continue;
        }

        //printf("Received packet from %s:%d\n", inet_ntoa(otherClient.sin_addr), ntohs(otherClient.sin_port));
        PacketData *packetData = dataToPacket(msgBuffer);
        if (packetData == NULL) {
            continue;
        }
        char flag = packetData->flag;

        switch (flag) {
            case 's': {
                PacketData *packetDataAck = createPacket('a');
                char *messageToSend2 = packetToData(packetDataAck, &sizee);
                if (sendto(s1, messageToSend2, 18, 0, (struct sockaddr *) &otherClient, slen) == SOCKET_ERROR) {
                    printf("sendto() failed with error code : %d\n", WSAGetLastError());
                    continue;
                }
                //free(packetDataAck);
                //free(messageToSend2);
                break;
            }
            case 'm': {
                if (receivingFile) {
                    FILE *fptr;
                    fptr = fopen(fileName, "a");
                    fprintf(fptr, "%s", packetData->data);
                    printf("Packet contains data: %s\n", packetData->data);
                    fclose(fptr);
                    if(packetData->fragNum == packetData->fragTotal){
                        receivingFile = 0;
                    }
                } else {
                    printf("Received packet n. %d\n", packetData->fragNum);
                    printf("Packet data length: %d\n", packetData->len);
                    printf("Packet contains data: %s\n", packetData->data);
                }
                break;
            }
            case 'f': {
                strcpy(fileName, packetData->data);
                printf("Receiving file: %s\n", fileName);
                printf("Receiving file: %s\n", packetData->data);
                receivingFile = 1;
                break;
            }
            default: {
                doRun = 0;
                break;
            }
        }

        free(packetData);
    }
    return 0;

}

DWORD WINAPI sendThreadFunc(LPVOID lpParam) {
    PacketData **fragments = NULL;
    int doRun = 1;
    char msgBuffer[1500];
    int actualSize = 0;

    int slen = sizeof(myClient);

    while (1) {
        printf("Enter message or -e to end messaging and return to menu:\n");
        fflush(stdin);
        scanf("%1500[^\n]", msgBuffer);
        getc(stdin);

        if (strcmp(msgBuffer, "-e") == 0) {
            isInside = 0;
            return 0;
        }

        if (strlen(msgBuffer) >= 1499) {
            continue;
        }

        fragments = makeFragments(msgBuffer);
        int numFragments = fragments[0]->fragTotal;
        printf("Number of fragments: %d\n", numFragments);

        PacketData *packetData = createPacket('s');
        if (packetData == NULL) {
            printf("Could not init packet 's'\n");
            continue;
        }
        char *sync = packetToData(packetData, &actualSize);


        if (sendto(s2, sync, 18, 0, (struct sockaddr *) &myClient,
                   slen) == SOCKET_ERROR) {
            printf("sendto() failed with error code : %d\n", WSAGetLastError());
            continue;
        }
        printf("First fragment sent.\n");

        free(packetData);

        char *ack = (char *) calloc(18, sizeof(char));
        if (recvfrom(s2, ack, 18, 0, (struct sockaddr *) &myClient, &slen) ==
            SOCKET_ERROR) {
            printf("recvfrom() failed with error code : %d\n", WSAGetLastError());
            continue;
        }
        free(ack);
        printf("Server confirmed first packet.\n");
        for (int i = 0; i < fragments[0]->fragTotal; i++) {
            char *msgBuffer2 = packetToData(fragments[i], &actualSize);
            if (sendto(s2, msgBuffer2, actualSize + 1, 0, (struct sockaddr *) &myClient,
                       slen) == SOCKET_ERROR) {
                printf("sendto() failed with error code : %d\n", WSAGetLastError());
                continue;
            }
        }
        free(fragments);
    }
    return 0;

}

DWORD WINAPI sendFileFunc(LPVOID lpParam) {
    char msgBuffer[1500];
    int actualSize = 0;

    int slen = sizeof(myClient);

    while (1) {
        printf("Enter file name or -e to return to menu:\n");
        fflush(stdin);
        scanf("%1500[^\n]", msgBuffer);
        getc(stdin);

        if (strcmp(msgBuffer, "-e") == 0) {
            isInside = 0;
            return 0;
        }

        if (strlen(msgBuffer) >= 1499) {
            continue;
        }

        //Get file length:
        FILE *fl = fopen(msgBuffer, "r");
        if (fl == NULL) {
            printf("Invalid name, try again\n");
            continue;
        }
        fseek(fl, 0, SEEK_END);
        long fileLength = ftell(fl);
        fclose(fl);



        int numFragments = (fileLength - 1) / fragSize + 2;
        printf("Number of fragments: %d\n", numFragments);

        PacketData *packetData = createPacket('s');
        if (packetData == NULL) {
            printf("Could not init packet 's'\n");
            continue;
        }
        char *sync = packetToData(packetData, &actualSize);


        if (sendto(s2, sync, 18, 0, (struct sockaddr *) &myClient,
                   slen) == SOCKET_ERROR) {
            printf("sendto() failed with error code : %d\n", WSAGetLastError());
            continue;
        }
        printf("First fragment sent.\n");

        free(packetData);

        char *ack = (char *) calloc(18, sizeof(char));
        if (recvfrom(s2, ack, 18, 0, (struct sockaddr *) &myClient, &slen) ==
            SOCKET_ERROR) {
            printf("recvfrom() failed with error code : %d\n", WSAGetLastError());
            continue;
        }
        //free(ack);
        PacketData *fragments = NULL;
        fragments = (PacketData *) malloc(sizeof(PacketData));
        fragments->data = (char *) malloc(fragSize * sizeof(char));
        strncpy(fragments->data, msgBuffer, strlen(msgBuffer));
        fragments->data[strlen(msgBuffer)] = '\0';
        fragments->flag = 'f';
        fragments->len = strlen(msgBuffer);
        fragments->fragNum = (unsigned int) (1);
        fragments->fragTotal = (unsigned int) numFragments - 1;
        fragments->CRC = (unsigned int) calculate_crc(msgBuffer, strlen(msgBuffer));

        //Sending the first fragment with 'f' flag
        char *toSend = packetToData(fragments, &actualSize);
        if (sendto(s2, toSend, actualSize + 1, 0, (struct sockaddr *) &myClient,
                   slen) == SOCKET_ERROR) {
            printf("sendto() failed with error code : %d\n", WSAGetLastError());
            continue;
        }


        printf("Server confirmed first packet.\n");
        size_t n = 0;
        int counter = 0;
        int fragNum = 2;
        int c;
        FILE *f2 = fopen(msgBuffer, "r");
        if(f2 == NULL){
            printf("File was null\n");
            continue;
        }
        while ((c = fgetc(f2)) != EOF) {
            msgBuffer[n++] = (char) c;

            counter++;
            if (counter == fragSize) {
                n = 0;
                counter = 0;

                printf("Allocating fragment number: %d\n", fragNum);
                PacketData *fragments2 = NULL;
                fragments2 = (PacketData *) malloc(sizeof(PacketData));
                if(fragments2 == NULL){
                    printf("Incorrect malloc\n");
                    break;
                }
                fragments2->data = (char *) malloc((fragSize+1) * sizeof(char));
                if(fragments2->data == NULL){
                    printf("Incorrect malloc2\n");
                    break;
                }
                strncpy(fragments2->data, msgBuffer, fragSize);
                printf("Copying data to fragment number: %d\n", fragNum);
                fragments2->data[strlen(msgBuffer)] = '\0';
                fragments2->flag = 'm';
                fragments2->len = (unsigned int) fragSize;
                fragments2->fragNum = (unsigned int) (fragNum);
                fragments2->fragTotal = (unsigned int) numFragments - 1;
                fragments2->CRC = (unsigned int) calculate_crc(msgBuffer, fragSize);

                printf("Allocated fragment number: %d\n", fragNum);

                fragNum++;

                char *toSend = packetToData(fragments2, &actualSize);
                if (sendto(s2, toSend, actualSize + 1, 0, (struct sockaddr *) &myClient,
                           slen) == SOCKET_ERROR) {
                    printf("sendto() failed with error code : %d\n", WSAGetLastError());
                    continue;
                }


                printf("Sent fragment number: %d\n", fragNum);

            }
        }

        fclose(fl);
    }
    return 0;

}

void p2pMode() {
    int serverPort, clientPort;
    char *serverAddr = (char *) malloc(20 * sizeof(char));
    WSADATA wsa;

    printf("\nInitialising Winsock...");
    if (WSAStartup(MAKEWORD(2, 2), &wsa) != 0) {
        printf("Failed. Error Code : %d", WSAGetLastError());
        getchar();
        exit(EXIT_FAILURE);
    }
    printf("Initialised.\n");
    char hostname[128] = "";
    char menuBuffer;
    gethostname(hostname, sizeof(hostname));
    struct hostent *ent = gethostbyname(hostname);
    struct in_addr ip_addr = *(struct in_addr *) (ent->h_addr);
    printf("Your IP Address: %s\n", inet_ntoa(ip_addr));

    printf("Enter other PC IP Address:\n");
    scanf("%s", serverAddr);
    if (!strcmp(serverAddr, "localhost"))
        serverAddr = (char *) "127.0.0.1";
    printf("Enter your listening port:\n");
    scanf("%d", &clientPort);
    printf("Enter other PC's port:\n");
    scanf("%d", &serverPort);

    if ((s1 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
        printf("Could not create socket : %d", WSAGetLastError());
    }
    if ((s2 = socket(AF_INET, SOCK_DGRAM, 0)) == INVALID_SOCKET) {
        printf("Could not create socket : %d", WSAGetLastError());
    }
    printf("Socket created.\n");

    server.sin_family = AF_INET;
    server.sin_addr.s_addr = inet_addr(inet_ntoa(ip_addr));
    server.sin_port = htons(clientPort);

    myClient.sin_family = AF_INET;
    myClient.sin_port = htons(serverPort);
    myClient.sin_addr.S_un.S_addr = inet_addr(serverAddr);

    if (bind(s1, (struct sockaddr *) &server, sizeof(server)) == SOCKET_ERROR) {
        printf("Bind failed with error code : %d", WSAGetLastError());
        exit(EXIT_FAILURE);
    }

    free(serverAddr);

    DWORD dwThreadId, dwThreadId2, dwThreadId3, dwThrdParam = 1;

    CreateThread(
            NULL, // default security attributes
            10000, // use default stack size
            receiveThreadFunc, // thread function
            &dwThrdParam, // argument to thread function
            0, // use default creation flags
            &dwThreadId); // returns the thread identifier
    while (1) {
        if (!isInside) {
            printf("For messages, write 'm', for file 'f'\n");
            scanf("%c", &menuBuffer);
            switch (menuBuffer) {
                case 'm':
                    CreateThread(
                            NULL, // default security attributes
                            10000, // use default stack size
                            sendThreadFunc, // thread function
                            &dwThrdParam, // argument to thread function
                            0, // use default creation flags
                            &dwThreadId2); // returns the thread identifier
                    isInside = 1;
                    break;
                case 'f':
                    CreateThread(
                            NULL, // default security attributes
                            10000, // use default stack size
                            sendFileFunc, // thread function
                            &dwThrdParam, // argument to thread function
                            0, // use default creation flags
                            &dwThreadId3); // returns the thread identifier
                    isInside = 1;
                    break;
            }
        }
    }
}

char *packetToData(PacketData *packet, int *size) { // convert packet into sendable data
    int sizee = packet->len + 18;
    *size = sizee;
    char *temp = (char *) calloc(sizee, sizeof(char));
    char *out;
    if (temp == NULL) {
        return NULL;
    }
    out = temp;
    *(temp) = packet->flag;
    *(unsigned int *) (temp + 2) = packet->CRC;
    *(unsigned int *) (temp + 6) = packet->fragNum;
    *(unsigned int *) (temp + 10) = packet->fragTotal;
    *(unsigned int *) (temp + 14) = packet->len;
    temp = (temp + 18);
    int i;
    for (i = 0; i < packet->len; i++) { // copy data
        temp[i] = packet->data[i];
    }
    temp[i] = '\0';
    return out;
}

PacketData *dataToPacket(char *data) { // convert received data into packet
    printf("Data received: %s\n", data);
    PacketData *packet = (PacketData *) malloc(sizeof(PacketData));
    if (packet == NULL)
        return NULL;
    packet->flag = *(data);
    packet->CRC = *(unsigned int *) (data + 2);
    packet->fragNum = *(unsigned int *) (data + 6);
    packet->fragTotal = *(unsigned int *) (data + 10);
    packet->len = *(unsigned int *) (data + 14);

    packet->data = (char *) malloc(packet->len);
    char *packetdata = (data + 18);
    int i;
    for (i = 0; i < packet->len; i++) { // copy data
        packet->data[i] = packetdata[i];
    }
    packet->data[i] = '\0';
    return packet;
}

PacketData *createPacket(char flag) {
    PacketData *packetData = (PacketData *) malloc(sizeof(PacketData));
    packetData->flag = flag;
    packetData->len = 0;
    packetData->CRC = 0;
    packetData->fragNum = 1;
    packetData->fragTotal = 1;
    return packetData;
}

int calculate_crc(char *buf, int size) {
    int crcHash = 10;
    for (int i = 0; i < size; i++) {
        crcHash += buf[i];
        crcHash *= 31;
        crcHash %= 30000;
    }
    return crcHash;
}

struct packetData **makeFragments(char *message) {
    int i;
    printf("Message length: %d\n", strlen(message));
    int fragCount = (strlen(message) - 1) / fragSize + 1;

    if (fragCount == 0) {
        fragCount++;
    }
    PacketData **fragments = (PacketData **) malloc((fragCount) * sizeof(PacketData *));
    printf("Allocated %d fragments\n", fragCount);

    for (i = 0; i < fragCount; i++) {
        fragments[i] = (PacketData *) malloc(sizeof(PacketData));
        fragments[i]->data = (char *) malloc(fragSize * sizeof(char));
        int toCopy = 0;
        if (strlen(message) > fragSize) {
            toCopy = fragSize;
        } else {
            toCopy = strlen(message);
        }
        strncpy(fragments[i]->data, message, toCopy);
        fragments[i]->data[toCopy] = '\0';
        fragments[i]->flag = 'm';
        fragments[i]->len = (unsigned int) toCopy;
        fragments[i]->fragNum = (unsigned int) (i + 1);
        fragments[i]->fragTotal = (unsigned int) fragCount;
        fragments[i]->CRC = (unsigned int) calculate_crc(message, toCopy);
        message += fragSize;

    }

    printf("Fragments needed: %d\n", fragments[0]->fragTotal);
    return fragments;
}

这是我的标头,如果有人需要运行它:

    //
// Created by lukas on 11/19/2018.
//

#include <winsock2.h>
#include <windows.h>

#ifndef PKS2C_MAIN_H
#define PKS2C_MAIN_H

#endif //PKS2C_MAIN_H

typedef struct packetData {
    char flag;
    unsigned int CRC;
    unsigned int fragNum;
    unsigned int fragTotal;
    unsigned int len;
    char *data;
} PacketData;

struct packetData **makeFragments(char *message);
struct packetData **makeFileFragments(char *message);

char *packetToData(PacketData *packet, int *size);

PacketData *dataToPacket(char *data);

PacketData *createPacket(char flag);

void p2pMode();

int calculate_crc(char *buf, int size);

DWORD WINAPI receiveThread(LPVOID lpParam);

DWORD WINAPI sendThread(LPVOID lpParam);

SOCKET s1, s2;
struct sockaddr_in server, myClient, otherClient;

0 个答案:

没有答案