0

我阅读了 Beej 的指南并创建了一个 UDP 服务器和客户端。我首先运行服务器,然后运行 ​​2 个客户端。服务器应该是recevfrom一个客户端和sendto另一个客户端。当客户端 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;  
}

谢谢你。

4

2 回答 2

2

在 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], not 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()");
            }
        }
于 2011-04-18T03:31:44.683 回答
1

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

        // 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]. 对我来说似乎是一个错误。

于 2011-04-18T03:37:44.587 回答