TCP服务器将接收消息返回给除C中发送方之外的所有客户端

时间:2017-03-24 07:03:07

标签: c sockets tcp qnx

这是我的代码

Server.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <mqueue.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

#define PORT 4444
#define BUF_SIZE 2000
#define CLADDR_LEN 100

void main() {
    struct sockaddr_in addr, cl_addr;
    int sockfd, len, ret, newsockfd,clientnumber;
    char buffer[BUF_SIZE];
    pid_t childpid;
    char clientAddr[CLADDR_LEN];


    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        printf("Error creating socket!\n");
        exit(1);
    }
    printf("Socket created...\n");

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = INADDR_ANY;
    addr.sin_port = PORT;

    ret = bind(sockfd, (struct sockaddr *) &addr, sizeof(addr));
    if (ret < 0) {
        printf("Error binding!\n");
        exit(1);
    }
    printf("Binding done...\n");
    clientnumber = 0;
    printf("Waiting for a connection...\n");
    listen(sockfd, 5);

    for (;;) { //infinite loop
        len = sizeof(cl_addr);
        newsockfd = accept(sockfd, (struct sockaddr *) &cl_addr, &len);
        if (newsockfd < 0) {
            printf("Error accepting connection!\n");
            exit(1);
        }
        printf("Connection accepted...\n");
        clientnumber++;
        inet_ntop(AF_INET, &(cl_addr.sin_addr), clientAddr, CLADDR_LEN);
        if ((childpid = fork()) == 0) { //creating a child process

            close(sockfd);
            //stop listening for new connections by the main process.
            //the child will continue to listen.
            //the main process now handles the connected client.


            sprintf(buffer, "USER%d", clientnumber);
            ret = sendto(newsockfd, buffer, BUF_SIZE, 0, (struct sockaddr *) &cl_addr, len);
            if (ret < 0){
                printf("Allocate Client number error\n");
                exit(1);
            }else{
                printf("Passing Client number : %d to Client Address %s ,  Newsockfd : %d ,claddr %d : \n",clientnumber,clientAddr,newsockfd,cl_addr);

            }


            for (;;) {
                memset(buffer, 0, BUF_SIZE);
                ret = recvfrom(newsockfd, buffer, BUF_SIZE, 0, (struct sockaddr *) &cl_addr, &len);
                if(ret < 0) {
                    printf("Error receiving data! from %s\n",clientAddr);
                    exit(1);
                }

                printf("Received data from %s(%d): %s\n", clientAddr,cl_addr.sin_addr.s_addr, buffer);


                ret = sendto(newsockfd, buffer, BUF_SIZE, 0, (struct sockaddr *) &cl_addr, len);
                if (ret < 0) {
                    printf("Error sending data! to %s\n",clientAddr);
                    exit(1);
                }
                printf("Sent data to %s: %s   Newsockfd : %d ,claddr %d :\n", clientAddr, buffer,newsockfd,cl_addr);

            }


        }
        close(newsockfd);
    }
}

Client.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <mqueue.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>



#define PORT 4444
#define BUF_SIZE 2000
#define MAX_SIZE    1024
#define MSG_STOP    "exit"

#define CHECK(x) \
        do { \
            if (!(x)) { \
                fprintf(stderr, "%s:%d: ", __func__, __LINE__); \
                perror(#x); \
                exit(-1); \
            } \
        } while (0) \

int createQUEUE_NAMEInSharedMemory(char * QUEUE_NAME ){
    char buffer[80], filename[200] = "/tmp/chat.txt";
    int fd, file_size, ret, size_written, size_read;
    void *addr;

    unlink( filename);
    fd = open( filename, O_CREAT|O_RDWR , 0777 );
    if( fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    size_written = write( fd, QUEUE_NAME, strlen(QUEUE_NAME) + 1 );
    if ( size_written == -1 ){
        perror("write");
        exit(0);
    }
    printf( "Wrote %d bytes into file %s\n", size_written, filename );

    lseek( fd, 0L, SEEK_SET );
    file_size = lseek( fd, 0L, SEEK_END );
    printf( "Size of file = %d bytes\n", file_size );

    /* Map the file into memory. */
    addr = mmap( 0, file_size, PROT_READ | PROT_WRITE , MAP_SHARED,
            fd, 0 );
    if (addr == MAP_FAILED) {
        perror("mmap");
        exit(EXIT_FAILURE);
    }

    /* Change the memory and synchronize it with the disk. */
    //                  memset( addr, 'B', 2 );
    //                  ret = msync( addr, file_size, MS_SYNC);
    //                  if( ret == -1) {
    //                      perror("msync");
    //                      exit(0);
    //                  }

    /* Close and reopen the file, and then read its contents. */
    close(fd);
    fd = open( filename, O_RDONLY);
    if( fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    size_read = read( fd, buffer, sizeof( buffer ) );
    printf( "File content = %s\n", buffer );

    close(fd);
    return EXIT_SUCCESS;
}



int main(){
    struct sockaddr_in addr, cl_addr;
    int sockfd, ret;
    char buffer[BUF_SIZE];
    struct hostent * server;
    char * serverAddr;
    char QUEUE_NAME[100];
    char * clientnumber;
    char temp[200];
    serverAddr = "127.0.0.1";
    printf("Server IP Address = %s\n",serverAddr);

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd < 0) {
        printf("Error creating socket!\n");
        exit(1);
    }
    printf("Socket created...\n");

    memset(&addr, 0, sizeof(addr));
    addr.sin_family = AF_INET;
    addr.sin_addr.s_addr = inet_addr(serverAddr);
    addr.sin_port = PORT;

    ret = connect(sockfd, (struct sockaddr *) &addr, sizeof(addr));
    if (ret < 0) {
        printf("Error connecting to the server!\n");
        exit(1);
    }
    printf("Connected to the server...\n");
    ret = recvfrom(sockfd, buffer, BUF_SIZE, 0, NULL, NULL);
    if (ret < 0) {
        printf("Error receiving data!\n");
    } else {
        clientnumber = malloc(200 * sizeof(char));
        memcpy(clientnumber, buffer, strlen(buffer)+1);
        clientnumber = realloc(clientnumber, strlen(clientnumber));
        sprintf(QUEUE_NAME, "/%s", clientnumber);

        printf("Received USER ID: ");
        fputs(buffer, stdout);
        printf("\n");

    }

    ret = createQUEUE_NAMEInSharedMemory(QUEUE_NAME);
    if(ret < 0){
        printf("Error Creating QUERE_NAME : %s !\n",QUEUE_NAME);
    }else{
        printf("Sending QUERE_NAME (%s) to shared memory successful!\n",QUEUE_NAME);
        mqd_t mq;
        struct mq_attr attr;
        char buffer[MAX_SIZE + 1];
        int must_stop = 0;

        /* initialize the queue attributes */
        attr.mq_flags = 0;
        attr.mq_maxmsg = 10;
        attr.mq_msgsize = MAX_SIZE;
        attr.mq_curmsgs = 0;

        /* create the message queue */
        mq = mq_open(QUEUE_NAME, O_CREAT | O_RDWR, 0644, &attr);
        CHECK((mqd_t)-1 != mq);
        printf("Creating MSG QUERE_NAME : %s \n",QUEUE_NAME);
        do {
            ssize_t bytes_read;

            /* receive the message */
            bytes_read = mq_receive(mq, buffer, MAX_SIZE, NULL);
            CHECK(bytes_read >= 0);

            buffer[bytes_read] = '\0';
            if (! strncmp(buffer, MSG_STOP, strlen(MSG_STOP)))
            {
                must_stop = 1;
            }
            else
            {
                printf("Received: %s\n", buffer);
                 memcpy(temp, buffer, strlen(buffer)+1);
                sprintf(buffer, "%s:%s", clientnumber,temp);
                 mq_send(mq, buffer, MAX_SIZE, 0);
                ret = sendto(sockfd, buffer, BUF_SIZE, 0, (struct sockaddr *) &addr, sizeof(addr));
                if (ret < 0) {
                    printf("Error sending data!\n\t-%s", buffer);
                }

                ret = recvfrom(sockfd, buffer, BUF_SIZE, 0, NULL, NULL);
                                if (ret < 0) {
                                    printf("Error receiving data!\n");
                                } else {
                                     mq_send(mq, buffer, MAX_SIZE, 0);
                                }


            }
        } while (!must_stop);
        printf("STOP MSG QUERE_NAME : %s \n",QUEUE_NAME);
        /* cleanup */
        CHECK((mqd_t)-1 != mq_close(mq));
        CHECK((mqd_t)-1 != mq_unlink(QUEUE_NAME));
    }



    //  memset(buffer, 0, BUF_SIZE);
    //  printf("%s: ",QUEUE_NAME);

    //  while (fgets(buffer, BUF_SIZE, stdin) != NULL) {
    //          ret = sendto(sockfd, buffer, BUF_SIZE, 0, (struct sockaddr *) &addr, sizeof(addr));
    //          if (ret < 0) {
    //              printf("Error sending data!\n\t-%s", buffer);
    //          }
    //          ret = recvfrom(sockfd, buffer, BUF_SIZE, 0, NULL, NULL);
    //          if (ret < 0) {
    //              printf("Error receiving data!\n");
    //          } else {
    //              printf("Received: ");
    //              fputs(buffer, stdout);
    //              printf("\n");
    //              //printf("Enter your message(s): ");
    //              printf("%s: ",QUEUE_NAME);
    //          }
    //      }
    free(clientnumber);
    return 0;
}

Input.c中

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <mqueue.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

#define MAX_SIZE    1024
#define MSG_STOP    "exit"

#define CHECK(x) \
        do { \
            if (!(x)) { \
                fprintf(stderr, "%s:%d: ", __func__, __LINE__); \
                perror(#x); \
                exit(-1); \
            } \
        } while (0) \


char QUEUE_NAME[100];

void GetQUERENAME(){
    char buffer[80], filename[200] = "/tmp/chat.txt";
    int fd, file_size, ret, size_written, size_read;
    void *addr;

    fd = open( filename, O_RDONLY);
    if( fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    size_read = read( fd, buffer, sizeof( buffer ) );
    //printf( "File content = %s\n", buffer );
    memcpy(QUEUE_NAME, buffer, strlen(buffer)+1);
    //printf("QUEUE_NAME length = %d\n",strlen(QUEUE_NAME));
    close(fd);
}



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

    GetQUERENAME();
    mqd_t mq;
    char buffer[MAX_SIZE];

    /* open the mail queue */
    mq = mq_open(QUEUE_NAME, O_WRONLY);
    CHECK((mqd_t)-1 != mq);


    printf("Send to Client QUERE_NAME : %s (enter \"exit\" to stop it):\n",QUEUE_NAME);

    do {
        printf("> ");
        fflush(stdout);

        memset(buffer, 0, MAX_SIZE);
        fgets(buffer, MAX_SIZE, stdin);

        /* send the message */
        CHECK(0 <= mq_send(mq, buffer, MAX_SIZE, 0));

    } while (strncmp(buffer, MSG_STOP, strlen(MSG_STOP)));

    /* cleanup */
    CHECK((mqd_t)-1 != mq_close(mq));




    return EXIT_SUCCESS;
}

output.c

#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <mqueue.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#include <sys/mman.h>
#include <fcntl.h>
#include <unistd.h>

#define MAX_SIZE    1024
#define MSG_STOP    "exit"

#define CHECK(x) \
        do { \
            if (!(x)) { \
                fprintf(stderr, "%s:%d: ", __func__, __LINE__); \
                perror(#x); \
                exit(-1); \
            } \
        } while (0) \


char QUEUE_NAME[100];

void GetQUERENAME(){
    char buffer[80], filename[200] = "/tmp/chat.txt";
    int fd, file_size, ret, size_written, size_read;
    void *addr;

    fd = open( filename, O_RDONLY);
    if( fd == -1) {
        perror("open");
        exit(EXIT_FAILURE);
    }
    size_read = read( fd, buffer, sizeof( buffer ) );
//  printf( "File content = %s\n", buffer );
    memcpy(QUEUE_NAME, buffer, strlen(buffer)+1);
//  printf("QUEUE_NAME length = %d\n",strlen(QUEUE_NAME));
    close(fd);
}



int main(int argc, char **argv)
{
    GetQUERENAME();
    mqd_t mq;
    struct mq_attr attr;
    char buffer[MAX_SIZE + 1];
    int must_stop = 0;

    /* initialize the queue attributes */
    attr.mq_flags = 0;
    attr.mq_maxmsg = 10;
    attr.mq_msgsize = MAX_SIZE;
    attr.mq_curmsgs = 0;

    /* create the message queue */
    mq = mq_open(QUEUE_NAME, O_CREAT | O_RDONLY, 0644, &attr);
    CHECK((mqd_t)-1 != mq);

    do {
        ssize_t bytes_read;

        /* receive the message */
        bytes_read = mq_receive(mq, buffer, MAX_SIZE, NULL);
        CHECK(bytes_read >= 0);

        buffer[bytes_read] = '\0';
        if (! strncmp(buffer, MSG_STOP, strlen(MSG_STOP)))
        {
            must_stop = 1;
        }
        else
        {
            printf("%s\n", buffer);
        }
    } while (!must_stop);

    /* cleanup */
    CHECK((mqd_t)-1 != mq_close(mq));
    CHECK((mqd_t)-1 != mq_unlink(QUEUE_NAME));

    return 0;
}

所以我尝试让服务器通过tcp协议接受客户端。接下来我尝试制作一个类似群聊的程序。在测试过程中,它从同一个IP地址连接的每个客户端。客户端连接到服务器后。客户端可以向服务器发送消息,反之亦然。在当前进程中,它仅向发送方返回消息。我想知道如何像广播一样将消息发送给除发件人之外的每个客户端。谢谢你的帮助。

1 个答案:

答案 0 :(得分:0)

第一步 - 放弃对fork()的呼叫。让每个客户通过一个完全独立的流程服务并不会让他们很容易意识到并能够相互交流。让服务器处理所有客户端要容易得多。

这是一个关于这样一个主循环可能是什么样的半伪代码。

while(1)
  {
  FD_ZERO(&readfds);
  FD_SET(sockfd,&readfds);
  for(each client FD)
    {
    FD_SET(clientfd,&readfds);
    }
  select(maxfds,&readfds,NULL,NULL,NULL);
  if(FD_ISSET(sockfd,&readfds))
    {
    /* accept() a new client */;
    }
  for(each client FD)
    {
    if(FD_ISSET(clientfd,&readfds))
      {
      /* read input */
      }
    }
  }

您希望缓冲来自客户端的输入,这样您就可以将完整的行发送给其他人,否则您将会看到人们正在编写的内容。并处理客户端断开连接。并且可能有一些方法可以确定哪个客户正在说什么。

如果你去寻找,有无数的完成MUD和谈话者的例子,你可以看看,以了解他们如何做你正在做的事情。