c - 将客户端发送的数据保存到队列中并进行解析

时间:2015-12-06 12:36:50

标签: c linux sockets

我正在尝试设置一个服务器程序,它将中间两个客户端。我正在尝试将客户端1发送的数据保存在服务器的链表列表中。

Server.c:

#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>

#define BUFLEN 512  //Max length of buffer
#define PORT 8888   //The port on which to listen for incoming data


struct node
{
    char *info;
    struct node *ptr;
}*front,*rear,*temp,*front1;

//int frontelement();
void enq(char data[]);
void deq();
void empty();
void display();
void create();
void queuesize();

int count = 0;

/* Create an empty queue */
void create()
{
    front = rear = NULL;
}

/* Returns queue size */
void queuesize()
{
    printf("\n Queue size : %d", count);
}

/* Enqueing the queue */
void enq(char data[])
{
    if (rear == NULL)
    {
        rear = (struct node *)malloc(1*sizeof(struct node));
        rear->ptr = NULL;
        rear->info = data;
        front = rear;
    }
    else
    {
        temp=(struct node *)malloc(1*sizeof(struct node));
        rear->ptr = temp;
        temp->info = data;
        temp->ptr = NULL;

        rear = temp;
    }
    count++;
}

/* Displaying the queue elements */
void display()
{
    front1 = front;

    if ((front1 == NULL) && (rear == NULL))
    {
        printf("Queue is empty");
        return;
    }
    while (front1 != rear)
    {
        printf("%s", front1->info);
        front1 = front1->ptr;
    }
    if (front1 == rear)
        printf("%s", front1->info);
}

/* Dequeing the queue */
void deq()
{
    front1 = front;

    if (front1 == NULL)
    {
        printf("\n Error: Trying to display elements from empty queue");
        return;
    }
    else
        if (front1->ptr != NULL)
        {
            front1 = front1->ptr;
            printf("\n Dequed value : %s", front->info);
            free(front);
            front = front1;
        }
        else
        {
            printf("\n Dequed value : %s", front->info);
            free(front);
            front = NULL;
            rear = NULL;
        }
        count--;
}

/* Display if queue is empty or not */
void empty()
{
     if ((front == NULL) && (rear == NULL))
        printf("\n Queue empty");
    else
       printf("Queue not empty");
}

void die(char *s)
{
    perror(s);
    exit(1);
}

int main(void)
{
    struct sockaddr_in si_me, si_other;

    int s, i, slen = sizeof(si_other) , recv_len;
    char buf[BUFLEN];

    //create a UDP socket
    if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    {
        die("socket");
    }

    // zero out the structure
    memset((char *) &si_me, 0, sizeof(si_me));

    si_me.sin_family = AF_INET;
    si_me.sin_port = htons(PORT);
    si_me.sin_addr.s_addr = htonl(INADDR_ANY);

    //bind socket to port
    if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)
    {
        die("bind");
    }

    //keep listening for data
    while(1)
    {
        printf("Waiting for data...");
        fflush(stdout);

        //try to receive some data, this is a blocking call
        if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == -1)
        {
            die("recvfrom()");
        }


        //print details of the client/peer and the data received
        printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port));
        printf("Data: %s\n" , buf);

            enq(buf);

    display();
    printf("\n");
        //now reply the client with the same data
        if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == -1)
        {
            die("sendto()");
        }
    }

    close(s);
    return 0;
}

Client.c:

#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>

#define SERVER "127.0.0.1"
#define BUFLEN 512  //Max length of buffer
#define PORT 8888   //The port on which to send data



void die(char *s)
{
    perror(s);
    exit(1);
}

int main(void)
{
    struct sockaddr_in si_other;
    int s, i, slen=sizeof(si_other);
    char buf[BUFLEN];
    char message[BUFLEN];

    if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
    {
        die("socket");
    }

    memset((char *) &si_other, 0, sizeof(si_other));
    si_other.sin_family = AF_INET;
    si_other.sin_port = htons(PORT);

    if (inet_aton(SERVER , &si_other.sin_addr) == 0)
    {
        fprintf(stderr, "inet_aton() failed\n");
        exit(1);
    }

    while(1)
    {
        printf("Enter message : ");
        gets(message);

        //send the message
        if (sendto(s, message, strlen(message) , 0 , (struct sockaddr *) &si_other, slen)==-1)
        {
            die("sendto()");
        }

        //receive a reply and print it
        //clear the buffer by filling null, it might have previously received data
        memset(buf,'\0', BUFLEN);
        //try to receive some data, this is a blocking call
        if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1)
        {
            die("recvfrom()");
        }

        puts(buf);
    }

    close(s);
    return 0;
}

当我将新数据发送到服务器时,它正在替换旧数据。有什么想法吗?感谢。

我也想定期向服务器发送有关客户端状态的消息。有关消息格式的任何建议吗?感谢

1 个答案:

答案 0 :(得分:0)

  

enq()正在存储数据   指向新分配的node,所以它们都结束了   指向同一个缓冲区。相反,它应该创建一个副本   数据。                        - keithmo

     抱歉,我不明白你的意思。你能详细说明吗?    - Shashank

尽管您致电enq(buf)并定义void enq(char data[]),但不会将数组char buf[BUFLEN]传递给enq(),而只会传递指向其第一个char的指针 - 这是因为( ISO / IEC 9899:201x ):

  

除非它是sizeof运算符的操作数,_Alignof   运算符,或一元&运算符,或者是用于的字符串文字   初始化一个数组,一个类型为''数组 type ''的表达式   转换为类型为''指向 type ''的表达式   指向数组对象的初始元素,而不是   左值。

因此,rear->info = data仅保存(始终相同)指针,而不保存接收到的数据。解决此问题的一种方法是将struct node的定义更改为

struct node
{
    char info[BUFLEN];
    struct node *ptr;
}

enq()使用strcpy()

void enq(char data[])
{
    temp = malloc(1*sizeof(struct node));
    temp->ptr = NULL;
    strcpy(temp->info, data);
    if (rear) rear->ptr = temp;
    else          front = temp;
    rear = temp;
    count++;
}

此外,由于buf内容用作字符串,因此我们必须确保'\0' recvfrom(s, buf, BUFLEN-1, …)终止buf[recv_len] = 0,然后设置1.4.0