C-IP中的UDP聊天应用程序打印为0.0.0.0

时间:2013-10-24 23:05:54

标签: c network-programming udp chat

我使用状态机模式创建了UDP聊天应用程序,但是当需要使用inet_ntoa打印IP地址时,终端会显示0.0.0.0

这是我的整个代码(我将它全部粘贴,所以你可以告诉我在哪里可以改进它。我在两周前开始学习C并且可以真的使用一些建议)

#include <stdio.h>          // stdin, fgets(), scanf(), printf()
#include <stdlib.h>         // exit()
#include <sys/socket.h>     // SOCK_DGRAM
#include <netinet/in.h>     // in_addr
#include <arpa/inet.h>      // inet_ntoa(), inet_aton()
#include <unistd.h>         // select()
#include <string.h>         // memset(), strcpy(), strerror()
#include <errno.h>          // errno
#include <ctype.h>          // isspace()

#define LISTENER_PORT 48879 // our 0xBEEF port :-)
#define BUFFER_SIZE 204     // 200 bytes plus 4 bytes of header
#define STDIN 0             // keyboard input

int chat_socket;            // this is the only socket used in the program

typedef struct              // struct the protocol
{
    unsigned char       version;            // 1 byte version number
    unsigned char       command;            // 1 byte command type
    unsigned char       seq;                // 1 byte sequence number
    unsigned char       ack;                // 1 byte acknowledgment number
    char                data[BUFFER_SIZE];  // 200 bytes message limit
} Packet;

Packet rxPacket;    // received packet instance
Packet txPacket;    // sent packet instance

enum states             // enumerate the states
{
    START,              // Send request to remote IP or wait for a request (WAIT_CONN_REQ)
    WAIT_RESP,          // Chat request sent to remote IP. Waiting for a response from the target machine
    SEND_CONN_RESP,     // Chat request received from remote IP. ACCEPT or REJECT
    ACCEPTED,           // Both parties agreed to exchange datagrams. Begin application data (MESSAGES) exchange
    STOP
};
typedef enum states states;
states state;

struct sockaddr_in my_address;
struct sockaddr_in sender_address;
struct sockaddr_in dest_address;

ssize_t r;
socklen_t sockLen = sizeof(struct sockaddr_in);

int WAIT_CONN_REQ(char *argv[])
{
    /* Bind the socket to the given port */
    if (bind(chat_socket, (struct sockaddr *)&my_address, sizeof(my_address))<0)
    {
        printf("UDP socket bind() error no %d: %s\n", errno, strerror(errno));
        exit(1);
    }

    printf("Socket bound to port %d!\nWaiting for CONN_REQ!\n", LISTENER_PORT);

    if (((r = recvfrom(chat_socket, &rxPacket, BUFFER_SIZE, 0, (struct sockaddr *)&sender_address, &sockLen)))<0)
    {
        printf("UDP recvfrom() error no %d: %s\n", errno, strerror(errno));
        exit(1);
    }

    if (rxPacket.command == 1)
    {
        int rsp = 0;
        char q = 0;
        while (q != 'A' && q != 'D')
        {
            printf("Connection request received from %s - [A]ccept or [D]ecline?\t", inet_ntoa(sender_address.sin_addr));
            scanf(" %c", &q);
        }
        if (q == 'A')
        {
            printf("You have accepted the connection request.\n");
            rsp = 3;
        }
        else if (q == 'D')
        {
            printf("You have declined the connection request.\n");
            rsp = 2;
        }
        if (rsp != 0)
        {
            strcpy(txPacket.data, "Name");
            txPacket.version    = 1;
            txPacket.command    = rsp;

            sendto(chat_socket, &txPacket, BUFFER_SIZE, 0, (struct sockaddr *)&sender_address, sizeof(sender_address));
            state = ACCEPTED;
        }
    }
    return(0);
}

void lookup(FILE *names, struct sockaddr_in myip[])
{
    char ipNr[32];
    char chatName[32];

    while(!feof(names))
    {
        fscanf(names, "%[^;];%s\n", ipNr, chatName);
        if (strcmp(ipNr, (const char*) myip) == 0)
        {
            printf("Found your IP in database\n");
            printf("IP: %s\n", ipNr);
            printf("Username: %s\n", chatName);
            printf("---\n");
            return;
        }
    }
}

void SEND_CONN_REQ(char *argv[])
{
    strcpy(txPacket.data, "Name");

    txPacket.version    = 1;
    txPacket.command    = 1;

    printf("Dest IP is %s\n", argv[0]);
    inet_aton(argv[0], &dest_address.sin_addr);

    sendto(chat_socket, &txPacket, BUFFER_SIZE, 0, (struct sockaddr *)&dest_address, sizeof(dest_address));
    printf("Chat request sent to %s - Waiting for a response\n", inet_ntoa(dest_address.sin_addr));

    state = WAIT_RESP;
}

void initialise()
{
    memset(&my_address.sin_zero, 0, sizeof(my_address.sin_zero));
    memset(&dest_address.sin_zero, 0, sizeof(dest_address.sin_zero));
    memset(&sender_address.sin_zero, 0, sizeof(sender_address.sin_zero));

    my_address.sin_family       = AF_INET;
    my_address.sin_addr.s_addr  = INADDR_ANY;
    my_address.sin_port         = htons(LISTENER_PORT);

    dest_address.sin_family     = AF_INET;
    dest_address.sin_port       = htons(LISTENER_PORT);

    if ((chat_socket = socket(AF_INET, SOCK_DGRAM, 0))<0)
    {
        printf("UDP socket allocation error no %d: %s\n", errno, strerror(errno));
        exit(1);
    }
}
void DATA_XCHANGE()
{
    while (1)
    {
        txPacket.version = 1;
        txPacket.command = 0;
        int len = sizeof(sender_address);
        fd_set readSet;
        FD_ZERO(&readSet);
        FD_SET(STDIN, &readSet);
        FD_SET(chat_socket, &readSet);
        if ((select(32, &readSet, NULL, NULL, NULL))>0)
        {
            if (FD_ISSET(STDIN, &readSet))
            {
                fgets(txPacket.data, BUFFER_SIZE, stdin);

                if (isspace(*txPacket.data) == 0)
                {
                    printf("You: %s", txPacket.data);
                    sendto(chat_socket, &txPacket, BUFFER_SIZE, 0, (struct sockaddr *)&sender_address, sizeof(sender_address));
                }
            }
            else if (FD_ISSET(chat_socket, &readSet))
            {
                if (((r = recvfrom(chat_socket, &rxPacket, BUFFER_SIZE, 0, (struct sockaddr *)&sender_address, (socklen_t *)&len)))<0)
                {
                    printf("UDP recvfrom() error no %d: %s\n", errno, strerror(errno));
                    exit(1);
                }
                if (rxPacket.command == 0)
                {
                    printf("message: %s", rxPacket.data);

                }
            }
        }
    }
}

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

    printf("your ip is %s", inet_ntoa(my_address.sin_addr));

    char *fname = "names.db";
    FILE *names = fopen(fname, "r");
    lookup(names, &my_address);


    state = START;

    while (state != STOP)
    {
        switch (state)
        {
            case START:
                printf("Simple Chat Client - START state\n");
                if (argv[1] != NULL)
                {
                    SEND_CONN_REQ(&argv[1]);
                }
                else
                {
                    WAIT_CONN_REQ(&argv[1]);
                }
                break;
            case WAIT_RESP:
                printf("WAIT_RESP STATE!\n");
                if (((r = recvfrom(chat_socket, &rxPacket, BUFFER_SIZE, 0, (struct sockaddr *)&sender_address, &sockLen)))<0)
                {
                    printf("UDP recvfrom() error no %d: %s\n", errno, strerror(errno));
                    exit(1);
                }
                if (rxPacket.command == 3)
                {
                    printf("Your connection request was accepted.\n");
                    state = ACCEPTED;
                }
                else if (rxPacket.command == 2)
                {
                    printf("Your connection request was declined.\n");
                    state = STOP;
                }
                break;
            case SEND_CONN_RESP:
                printf("SEND_CONN_RESP state!\n");
                break;
            case ACCEPTED:
                printf("ACCEPTED state!\n");
                DATA_XCHANGE();
                break;
            case STOP:
                printf("STOPPED! (switch)\n");
                break;
        }
    }
    printf("STOPPED! main()\n");
}

printf()函数中initialise()下面的main()0.0.0.0

的打印位置

同样,我会非常感谢此时的任何编码建议。它有助于学习过程!

1 个答案:

答案 0 :(得分:4)

你的程序正在按照预期完成。

0.0.0.0INADDR_ANY的值 - 换句话说,绑定到所有可用的接口。

在此处设置时:

my_address.sin_addr.s_addr  = INADDR_ANY;

你将它设置为0,并告诉它绑定任何它可以。