C 中的 UDP 服务器和 2 个 UDP 客户端

发布于 2024-11-01 15:53:48 字数 6702 浏览 5 评论 0原文

我阅读了 Beej 的指南并创建了一个 UDP 服务器和客户端。我首先运行服务器,然后运行 ​​2 个客户端。服务器应该从客户端接收并发送到另一个客户端。当客户端 1 发送某些内容时,客户端 0 会收到它。当客户端 0 发送某些内容时,客户端 1 没有收到。谁能看出代码有什么问题吗?我已阅读有关 UDP、C、服务器、聊天的所有问题,但找不到任何对我有帮助的内容。我正在 OSX 上编译此代码。任何帮助表示赞赏。以下是服务器代码:

 #include <arpa/inet.h>  
 #include <netinet/in.h>  
 #include <stdio.h>  
 #include <sys/types.h>  
 #include <sys/socket.h>  
 #include <unistd.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #define BUFLEN 512  
 #define PORT 7777  

 void err(char *str)  
 {  
     perror(str);  
     exit(1);  
 }  

 int main(void)  
 {  
     struct sockaddr_in my_addr, cli_addr[2],cli_temp;  
     int sockfd;  
     socklen_t slen[2],slen_temp;
     slen[1]=sizeof(cli_addr[1]); 
     slen[2]=sizeof(cli_addr[2]);
     slen_temp = sizeof(cli_temp);
     char buf[BUFLEN];  
     int clients = 0;
     int client_port[2];

     if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
     {
         printf("test\n");
         err("socket");  
     }else{  
         printf("Server : Socket() successful\n");  
     }   
     bzero(&my_addr, sizeof(my_addr));  
     my_addr.sin_family = AF_INET;  
     my_addr.sin_port = htons(PORT);  
     my_addr.sin_addr.s_addr = htonl(INADDR_ANY);  

     if (bind(sockfd, (struct sockaddr* ) &my_addr, sizeof(my_addr))==-1)
     {
         err("bind");  
     }else{
         printf("Server : bind() successful\n");  
     }

     while(1)  
     {
         //receive
         printf("Receiving...\n");
         if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_temp, &slen_temp)==-1)  
             err("recvfrom()");
         if (clients==0) {
             //first connection
             //store the temp connection details to the array
             cli_addr[0] = cli_temp;
             //get client 0 port
             client_port[0] = ntohs(cli_addr[0].sin_port);
             clients++;
             printf("Client 0 connected. Port: %d\n",client_port[0]);
             sendto(sockfd, "You are the only client.", 24, 0, (struct sockaddr*)&cli_temp, slen_temp);
         }else if (clients==1) {
             //new or existing
             if (client_port[0]==ntohs(cli_temp.sin_port)) {
                 //send back to client 0 that nobody else connected yet
                 sendto(sockfd, "You are the only client.", 24, 0, (struct sockaddr*)&cli_addr[0], slen[0]);
                 printf("Only client\n");
             }else{
                 //new connection
                 cli_addr[1] = cli_temp;
                 client_port[1] = ntohs(cli_addr[1].sin_port);
                 clients++;
                 printf("GOt second client\n");
                 sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[0], slen[0]);
             }
        }else{
            //there are 2 clients connected here. If we get an error from the sendto then we decrement clients
            if (client_port[0]==ntohs(cli_temp.sin_port)) {
                //client 0 talking send to client 1
                printf("Sedning message to client 1\n");
                if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[1], slen[1])==-1)
                {
                    clients--;
                    err("sendto()");
                }
            }else {
                //client 1 talking send to client 0
                printf("Sending message to client 0\n");
                if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[1], slen[1])==-1)
                {
                    clients--;
                    err("sendto()");
                }
            }

        }
        //printf("Received packet from %s:%d\nData: %s\n",  
        //        inet_ntoa(cli_addr[clients].sin_addr), ntohs(cli_addr[clients].sin_port), buf);  
     }  

     close(sockfd);  
     return 0;  
}

客户端:

#include <arpa/inet.h>  
#include <netinet/in.h>  
#include <stdio.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <string.h>
#include <sys/wait.h>
#include <signal.h>
#define BUFLEN 512  
#define PORT 7777  

void err(char *s)  
{  
    perror(s);  
    exit(1);  
}  
sig_atomic_t child_exit_status;

void clean_up_child_process (int signal_number) 
{
    /* Clean up the child process. */ 
    int status; 
    wait (&status); 
    /* Store its exit status in a global variable. */ 
    child_exit_status = status;
}
 int main(int argc, char** argv)  
 {  
     struct sockaddr_in serv_addr;  
     int sockfd, slen=sizeof(serv_addr);  
     char buf[BUFLEN];  
     struct sigaction sigchld_action; 
     memset (&sigchld_action, 0, sizeof (sigchld_action)); 
     sigchld_action.sa_handler = &clean_up_child_process; 
     sigaction (SIGCHLD, &sigchld_action, NULL);
     int pid,ppid;

     if(argc != 2)  
     {  
       printf("Usage : %s <Server-IP>\n",argv[0]);  
       exit(0);  
     }  

     if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)  
         err("socket");  

     bzero(&serv_addr, sizeof(serv_addr));  
     serv_addr.sin_family = AF_INET;  
     serv_addr.sin_port = htons(PORT);  
     if (inet_aton(argv[1], &serv_addr.sin_addr)==0)  
     {  
         fprintf(stderr, "inet_aton() failed\n");  
         exit(1);  
     }
     pid = fork();
     if (pid<0) {
         err("Fork Error");
     }else if (pid==0) {
         //child process will receive from server
         while (1) {
             bzero(buf,BUFLEN);
             printf("Attempting to READ to socket %d: ",sockfd);
             fflush(stdout);
             //recvfrom here
             if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, &slen)==-1)  
                 err("recvfrom()");

             printf("The message from the server is: %s \n",buf);
             if (strcmp(buf,"bye\n") == 0) {
                 ppid = getppid();
                 kill(ppid, SIGUSR2);

                 break;
             }
         }
     }else {
         //parent will send to server
         while(1){
             printf("Please enter the message to send: ");
             bzero(buf,BUFLEN);
             fgets(buf,BUFLEN,stdin);
             printf("Attempting to write to socket %d: ",sockfd);
             fflush(stdout);
             //send to here
             if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, slen)==-1)
             {
                 err("sendto()");
             }
         }
     }
     close(sockfd);  
     return 0;  
}

谢谢。

I read Beej's guide and created a UDP server and client. I first run the server and then run 2 clients. The server is supposed to recevfrom a client and sendto the other client. When client 1 sends something client 0 receives it. When client 0 sends something client 1 does not receive it. Can anyone see what is wrong with the code? I have read all questions on UDP, C, server, chat but was unable to find anything that helped me. I am compiling this code on OSX. Any help is appreciated. Following is the server code:

 #include <arpa/inet.h>  
 #include <netinet/in.h>  
 #include <stdio.h>  
 #include <sys/types.h>  
 #include <sys/socket.h>  
 #include <unistd.h>  
 #include <stdlib.h>  
 #include <string.h>  
 #define BUFLEN 512  
 #define PORT 7777  

 void err(char *str)  
 {  
     perror(str);  
     exit(1);  
 }  

 int main(void)  
 {  
     struct sockaddr_in my_addr, cli_addr[2],cli_temp;  
     int sockfd;  
     socklen_t slen[2],slen_temp;
     slen[1]=sizeof(cli_addr[1]); 
     slen[2]=sizeof(cli_addr[2]);
     slen_temp = sizeof(cli_temp);
     char buf[BUFLEN];  
     int clients = 0;
     int client_port[2];

     if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)
     {
         printf("test\n");
         err("socket");  
     }else{  
         printf("Server : Socket() successful\n");  
     }   
     bzero(&my_addr, sizeof(my_addr));  
     my_addr.sin_family = AF_INET;  
     my_addr.sin_port = htons(PORT);  
     my_addr.sin_addr.s_addr = htonl(INADDR_ANY);  

     if (bind(sockfd, (struct sockaddr* ) &my_addr, sizeof(my_addr))==-1)
     {
         err("bind");  
     }else{
         printf("Server : bind() successful\n");  
     }

     while(1)  
     {
         //receive
         printf("Receiving...\n");
         if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_temp, &slen_temp)==-1)  
             err("recvfrom()");
         if (clients==0) {
             //first connection
             //store the temp connection details to the array
             cli_addr[0] = cli_temp;
             //get client 0 port
             client_port[0] = ntohs(cli_addr[0].sin_port);
             clients++;
             printf("Client 0 connected. Port: %d\n",client_port[0]);
             sendto(sockfd, "You are the only client.", 24, 0, (struct sockaddr*)&cli_temp, slen_temp);
         }else if (clients==1) {
             //new or existing
             if (client_port[0]==ntohs(cli_temp.sin_port)) {
                 //send back to client 0 that nobody else connected yet
                 sendto(sockfd, "You are the only client.", 24, 0, (struct sockaddr*)&cli_addr[0], slen[0]);
                 printf("Only client\n");
             }else{
                 //new connection
                 cli_addr[1] = cli_temp;
                 client_port[1] = ntohs(cli_addr[1].sin_port);
                 clients++;
                 printf("GOt second client\n");
                 sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[0], slen[0]);
             }
        }else{
            //there are 2 clients connected here. If we get an error from the sendto then we decrement clients
            if (client_port[0]==ntohs(cli_temp.sin_port)) {
                //client 0 talking send to client 1
                printf("Sedning message to client 1\n");
                if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[1], slen[1])==-1)
                {
                    clients--;
                    err("sendto()");
                }
            }else {
                //client 1 talking send to client 0
                printf("Sending message to client 0\n");
                if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[1], slen[1])==-1)
                {
                    clients--;
                    err("sendto()");
                }
            }

        }
        //printf("Received packet from %s:%d\nData: %s\n",  
        //        inet_ntoa(cli_addr[clients].sin_addr), ntohs(cli_addr[clients].sin_port), buf);  
     }  

     close(sockfd);  
     return 0;  
}

And the client:

#include <arpa/inet.h>  
#include <netinet/in.h>  
#include <stdio.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <unistd.h>  
#include <stdlib.h>  
#include <string.h>
#include <sys/wait.h>
#include <signal.h>
#define BUFLEN 512  
#define PORT 7777  

void err(char *s)  
{  
    perror(s);  
    exit(1);  
}  
sig_atomic_t child_exit_status;

void clean_up_child_process (int signal_number) 
{
    /* Clean up the child process. */ 
    int status; 
    wait (&status); 
    /* Store its exit status in a global variable. */ 
    child_exit_status = status;
}
 int main(int argc, char** argv)  
 {  
     struct sockaddr_in serv_addr;  
     int sockfd, slen=sizeof(serv_addr);  
     char buf[BUFLEN];  
     struct sigaction sigchld_action; 
     memset (&sigchld_action, 0, sizeof (sigchld_action)); 
     sigchld_action.sa_handler = &clean_up_child_process; 
     sigaction (SIGCHLD, &sigchld_action, NULL);
     int pid,ppid;

     if(argc != 2)  
     {  
       printf("Usage : %s <Server-IP>\n",argv[0]);  
       exit(0);  
     }  

     if ((sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))==-1)  
         err("socket");  

     bzero(&serv_addr, sizeof(serv_addr));  
     serv_addr.sin_family = AF_INET;  
     serv_addr.sin_port = htons(PORT);  
     if (inet_aton(argv[1], &serv_addr.sin_addr)==0)  
     {  
         fprintf(stderr, "inet_aton() failed\n");  
         exit(1);  
     }
     pid = fork();
     if (pid<0) {
         err("Fork Error");
     }else if (pid==0) {
         //child process will receive from server
         while (1) {
             bzero(buf,BUFLEN);
             printf("Attempting to READ to socket %d: ",sockfd);
             fflush(stdout);
             //recvfrom here
             if (recvfrom(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, &slen)==-1)  
                 err("recvfrom()");

             printf("The message from the server is: %s \n",buf);
             if (strcmp(buf,"bye\n") == 0) {
                 ppid = getppid();
                 kill(ppid, SIGUSR2);

                 break;
             }
         }
     }else {
         //parent will send to server
         while(1){
             printf("Please enter the message to send: ");
             bzero(buf,BUFLEN);
             fgets(buf,BUFLEN,stdin);
             printf("Attempting to write to socket %d: ",sockfd);
             fflush(stdout);
             //send to here
             if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&serv_addr, slen)==-1)
             {
                 err("sendto()");
             }
         }
     }
     close(sockfd);  
     return 0;  
}

Thank you.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

睡美人的小仙女 2024-11-08 15:53:48

在 main 的开头,你有这样的代码:

 struct sockaddr_in my_addr, cli_addr[2],cli_temp;  
 int sockfd;  
 socklen_t slen[2],slen_temp;
 slen[1]=sizeof(cli_addr[1]); 
 slen[2]=sizeof(cli_addr[2]);

这应该更改为:

 struct sockaddr_in my_addr, cli_addr[2],cli_temp;  
 int sockfd;  
 socklen_t slen[2],slen_temp;
 slen[0]=sizeof(cli_addr[0]); 
 slen[1]=sizeof(cli_addr[1]);

我浏览了你的代码的其余部分,没有看到任何其他错误。我不确定这是否能解决你的问题,但这绝对是错误的。

(你可能知道这一点,但是)这是错误的,因为数组的第一个元素是 array[0],而不是 array[1],所以如果你有一个数组2 个元素,则 array[2] 将不存在。

更新

更改

else {
            //client 1 talking send to client 0
            printf("Sending message to client 0\n");
            if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[1], slen[1])==-1)
            {
                clients--;
                err("sendto()");
            }
        }

else {
            //client 1 talking send to client 0
            printf("Sending message to client 0\n");
            if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[0], slen[1])==-1)
            {
                clients--;
                err("sendto()");
            }
        }

In the beginning of main, you've got this code:

 struct sockaddr_in my_addr, cli_addr[2],cli_temp;  
 int sockfd;  
 socklen_t slen[2],slen_temp;
 slen[1]=sizeof(cli_addr[1]); 
 slen[2]=sizeof(cli_addr[2]);

This should be changed to:

 struct sockaddr_in my_addr, cli_addr[2],cli_temp;  
 int sockfd;  
 socklen_t slen[2],slen_temp;
 slen[0]=sizeof(cli_addr[0]); 
 slen[1]=sizeof(cli_addr[1]);

I browsed the rest of your code and didn't see any other errors. I'm not sure if this will fix your problem, but it's definitely wrong.

(you probably know this, but) it's wrong because the first element of an array is array[0], not array[1], so if you have an array with 2 elements, then array[2] won't exist.

Update

Change

else {
            //client 1 talking send to client 0
            printf("Sending message to client 0\n");
            if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[1], slen[1])==-1)
            {
                clients--;
                err("sendto()");
            }
        }

to

else {
            //client 1 talking send to client 0
            printf("Sending message to client 0\n");
            if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[0], slen[1])==-1)
            {
                clients--;
                err("sendto()");
            }
        }
亢潮 2024-11-08 15:53:48

在您的代码中,您有以下内容:

        // there are 2 clients connected here. If we get an error from the sendto
        // then we decrement clients
        if (client_port[0]==ntohs(cli_temp.sin_port)) {
            //client 0 talking send to client 1
            printf("Sedning message to client 1\n");
            if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[1], slen[1])==-1)
            {
                clients--;
                err("sendto()");
            }
        }else {
            //client 1 talking send to client 0
            printf("Sending message to client 0\n");
            if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[1], slen[1])==-1)
            {
                clients--;
                err("sendto()");
            }
        }

请注意,两个部分(1 到 0,以及 0 到 1)都发送到 &cli_addr[1]。对我来说看起来像一个错误。

In your code, you have the following:

        // there are 2 clients connected here. If we get an error from the sendto
        // then we decrement clients
        if (client_port[0]==ntohs(cli_temp.sin_port)) {
            //client 0 talking send to client 1
            printf("Sedning message to client 1\n");
            if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[1], slen[1])==-1)
            {
                clients--;
                err("sendto()");
            }
        }else {
            //client 1 talking send to client 0
            printf("Sending message to client 0\n");
            if (sendto(sockfd, buf, BUFLEN, 0, (struct sockaddr*)&cli_addr[1], slen[1])==-1)
            {
                clients--;
                err("sendto()");
            }
        }

Notice that both sections (1 to 0, as well as 0 to 1) send to &cli_addr[1]. Looks like a bug to me.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文