简体   繁体   English

C ++使用UDP发送数据报

[英]C++ Sending datagrams with UDP

Hello again stackoverflow! 您好,再次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 . 您总是试图接收64个字节,但要根据echolen检查返回值。 The value in echolen is the length message which may not be exactly 64 bytes. echolen的值是长度message ,可能不完全是64个字节。 You also are not checking all possible conditions returned by recvfrom . 您也没有检查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. 如果返回0,则连接被另一端关闭;如果返回-1,则发生错误,并且其他任何值都是接收到的字节数。

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. 如果您尝试读取64个字节,并且消息的长度更大,则数据报中所有未读取的字节将被丢弃。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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