简体   繁体   中英

C++ Sending datagrams with UDP

Hello again stackoverflow!

I've had my professor assign me a program that would try and take user input for credit card info, send it to a server with the database in a upd datagram and print what is returned.

I think I am almost done but one of my perrors is going off when trying to send the info to the server.

The perror is

Mismatch in number of sent bytes: Permission Denied

I'm at a loss at what to do so any advice would be appreciated :) I've posted my code below:

#include <iostream>
#include <cstring>
#include <string>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <netinet/in.h>
#include <cstdio>
#include <cstdlib>

using namespace std;

int countDigits(char[], int);
int findDec(char[],int);
int findLastEle(char[]);
int findSlash(char[],int);

int main() {

    //variables
    char cardNum[64], cardName[64], expDate[8], cardAmt[64], message[64]; //User input variables and datagram message

    int cardNumlen, cardDigits, amtLen, decVar, lastVar,
        expLast, expEle, expLen, sock, echolen, received = 0;
    char buffer[64];

    unsigned int addrlen;

    struct sockaddr_in echoserver;  // structure for address of server

    //Welcome the user
    cout << "Welcome to the Credit Card Transaction verification utility!\n";

    //ask user for card holder name or quit
    cout << "Enter card holder name (or quit): ";
    cin.getline(cardName, 64);

    //Make loop that will quit if quit chosen
    while(strcmp(cardName, "quit") != 0){
        //Ask for numbers
        cout << "Enter CC number: ";
        cin.getline(cardNum, 64);

        //count number of digets
        cardNumlen = strlen(cardNum);
        cardDigits = countDigits(cardNum, cardNumlen);

        //make sure there are 15-16 digits
        while(cardDigits < 15 or cardDigits > 16){
            cout << "You have entered an invalid CC number. Please try again: ";
            cin.getline(cardNum, 64);
            cardNumlen = strlen(cardNum);
            cardDigits = countDigits(cardNum, cardNumlen);
        }

        //ask for experation date
        do{
            cout << "Enter experation (form mm/yyyy): ";
            cin.getline(expDate, 8);
            expLen = strlen(expDate);
            expEle = findSlash(expDate, expLen);
            expLast = findLastEle(expDate);
        }while(expEle != (expLast - 5));

        //ask for card amount
        cout << "Enter amount: ";
        cin.getline(cardAmt, 64);

        //find . in char array
        amtLen = strlen(cardAmt);
        decVar = findDec(cardAmt, amtLen);

        //find last character in array
        lastVar = findLastEle(cardAmt);
        //Make sure . is in right spot
        while(decVar != (lastVar - 3)){

            //ask for card amount again if fail
            cout << "You entered an invalid amount! Please try again: ";
            cin.getline(cardAmt, 64);

            //find . in char array
            amtLen = strlen(cardAmt);
            decVar = findDec(cardAmt, amtLen);

            //find last character in array
            lastVar = findLastEle(cardAmt);
        }

        cout << "Verifying...\n";

        //Make the message by looping
        // through message and putting 
        // each character into message
        strcpy(message, cardNum);
        strcat(message, ":");
        strcat(message, expDate);
        strcat(message, ":");
        strcat(message, cardAmt);
        strcat(message, ":");
        strcat(message, cardName);

        // Create the UDP socket
        if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
            perror("Failed to create socket");
            exit(EXIT_FAILURE);
        }

        // Construct the server sockaddr_in structure
        memset(&echoserver, 0, sizeof(echoserver));
        echoserver.sin_family = AF_INET;                  //Internet IP
        echoserver.sin_addr.s_addr = inet_addr("IPADDRESSHERE");  //IP address
        echoserver.sin_port = htons(PORTHERE);       //server port

        // Send the message to the server 
        echolen = strlen(message);
        if (sendto(sock, message, strlen(message), 0, (struct sockaddr *) &echoserver, sizeof(echoserver)) != echolen) {
            perror("Mismatch in number of sent bytes");
            exit(EXIT_FAILURE);
        }

        // Receive the message back from the server 
        addrlen = sizeof(echoserver);
        if ((received = recvfrom(sock, buffer, 64, 0, (struct sockaddr *) &echoserver, &addrlen)) != echolen) {
            perror("Mismatch in number of received bytes");
            exit(EXIT_FAILURE);
        }

        buffer[received] = '\0';        /* Assure null-terminated string */
        cout << buffer << endl;

        close(sock); // closing the sock

        //Restart the while(maybe quit) loop
        //ask user for card holder name or quit
        cout << "\nEnter card holder name (or quit): ";
        cin.getline(cardName, 64);

    }//end of while loop for quit
    return 0;
}

These are the functions I made to help get user input

    //countDigits function
    int countDigits(char array[], int strLen){
        int i, digits = 0;
        for( i = 0; i < strLen; i++){
            if( array[i] == ' '){
                digits--;
            }
            digits++;
        }
        return digits;

    }

    //findDec function (finds decimal place in array)
    int findDec(char array[], int arrayLen){
        int r, dec = 0;

        for(r = 0; r < arrayLen; r++){
            if(array[r] == '.'){
                break;
            }
            else{
                dec++;
            }
        }

        return dec;
    }

    //Finds the last element in a array
    int findLastEle(char array[]){
        int i, last;
        while(array[i]){
            i++;
            last++;
        }

        return last;
    }

    //findSlash function (finds slash place in array)
    int findSlash(char array[], int arrayLen){
        int r, dec = 0;

        for(r = 0; r < arrayLen; r++){
            if(array[r] == '/'){
                break;
            }
            else{
                dec++;
            }
        }

        return dec;
    }

You are always trying to receive 64 bytes but checking the return value against echolen . The value in echolen is the length message which may not be exactly 64 bytes. You also are not checking all possible conditions returned by recvfrom . If it returns 0 the connection was closed by the other side, if it returns -1 an error occurred and any other value is the number of bytes received.

Be aware datagram socket are message based. If you try to read 64 bytes and the length of the message is bigger all unread bytes in the datagram will be discarded.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM