简体   繁体   English

如何确定哪个客户端在UDP套接字编程中发送了消息

[英]How to determine which client sent the message in UDP socket programming

I'm creating a two way chat program using C This is the code for the server 我正在使用C创建一个双向聊天程序。这是服务器的代码

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<signal.h>
// the port users will be connecting to
#define RCVPORT "4950"
#define MAXBUFLEN 100

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa){
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }
    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(void){
int sockfd;
struct addrinfo hints,*servinfo,*p1;
int rv;
int numbytes;
int yes = 1;
struct sockaddr_storage client1_addr,client2_addr;
char buf[MAXBUFLEN];
char buf2[MAXBUFLEN];
char auth[6],auth2[6];
socklen_t client1_addrlen,client2_addrlen;
char s[INET6_ADDRSTRLEN];
pid_t pid1,pid2;    
char exiter[20];
memset(&hints, 0, sizeof hints);

hints.ai_family = AF_UNSPEC; // set to AF_INET to force IPv4
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP


if ((rv = getaddrinfo(NULL, RCVPORT, &hints, &servinfo)) != 0) {
    fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
    return 1;
}
// loop through all the results and bind to the first we can
for(p1 = servinfo; p1 != NULL; p1 = p1->ai_next) {
    if ((sockfd = socket(p1->ai_family, p1->ai_socktype,p1->ai_protocol)) == -1) {
        perror("listener: socket");
        continue;
    }
    if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,sizeof(int)) == -1) {
        perror("setsockopt");
        exit(1);
    }
    if (bind(sockfd, p1->ai_addr, p1->ai_addrlen) == -1) {
        close(sockfd);
        perror("listener: bind");
        continue;
    }
    break;
}
if (p1 == NULL) {
    fprintf(stderr, "listener: failed to bind socket\n");
    return 2;
}
freeaddrinfo(servinfo);

client1_addrlen = sizeof(client1_addr);
client2_addrlen = sizeof(client2_addr); 
//WAIT for CLIENT 1 
printf("listener: waiting for clients...\n");
if ((numbytes = recvfrom(sockfd,auth, MAXBUFLEN-1 , 0,(struct sockaddr *)&client1_addr, &client1_addrlen)) == -1) {
    perror("recvfrom");
    exit(1);
}
if(strcmp(auth,"AUTH")!=0){
    printf("CLIENT AUTHENTICATION FAILED");     
    exit(0);    
}
printf("GOT CLIENT 1!!\n");
//WAIT for CLIENT 2 
if ((numbytes = recvfrom(sockfd,auth2, MAXBUFLEN-1 , 0,(struct sockaddr *)&client2_addr, &client2_addrlen)) == -1) {
        perror("recvfrom");
        exit(1);
}
if(strcmp(auth2,"AUTH")!=0){
    printf("CLIENT AUTHENTICATION FAILED");     
    exit(0);    
}
if ((numbytes=sendto(sockfd,"ok",3,0,(struct sockaddr *)&client1_addr, client1_addrlen)) == -1) {
    perror("talker: sendto");
    exit(1);
}
if ((numbytes=sendto(sockfd,"ok",3,0,(struct sockaddr *)&client2_addr, client2_addrlen)) == -1) {
    perror("talker: sendto");
    exit(1);
}
printf("GOT CLIENT 2!!!\n");
printf("Server Ready!!!\n");
//for CLIENT 1
if(fork()==0){
    while(1){
        if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN-1 , 0,NULL,NULL)) == -1) {
            perror("recvfrom");
            exit(1);
        }

        if(numbytes!=0){
            printf("listener: packet contains %s \n", buf);
            if ((numbytes=sendto(sockfd, buf, strlen(buf)+1,0,(struct sockaddr *)&client2_addr, client2_addrlen)) == -1) {
                perror("talker: sendto");
                exit(1);
            }
        }
        else{
            printf("CLIENT 1 has disconnected\n");
            break;          
        }

    }
    exit(0);

}
//for CLIENT 2
if(fork()==0){
    while(1){
        if ((numbytes = recvfrom(sockfd, buf2, MAXBUFLEN-1 , 0,NULL,NULL)) == -1) {
            perror("recvfrom");
            exit(1);
        }

        printf("listener: packet contains %s \n", buf2);

        if(numbytes!=0){            
            if ((numbytes=sendto(sockfd, buf2, strlen(buf2)+1,0,(struct sockaddr *)&client1_addr, client1_addrlen)) == -1) {
                perror("talker: sendto");
                exit(1);
            }
        }
        else{
            printf("CLIENT 2 has disconnected\n");
            break;      
        }       
    }
    exit(0);

}
wait(NULL);
//fgets(exiter,sizeof(exiter),stdin);
close(sockfd);

return 0;}

Then this is the code for the client 这是客户端的代码

#include<stdio.h>
#include<stdlib.h>
#include<unistd.h>
#include<errno.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<netdb.h>
#include<signal.h>
#define SERVERPORT "4950"
#define MAXBUFLEN 100
// the port users will be connecting to
int main(int argc, char *argv[]){
    int sockfd;
    char ok[3];
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_storage server_addr;
    socklen_t server_addrlen = sizeof(server_addr);
    int rv;
    int numbytes;
    char sendbuffer[256];
    char rcvbuffer[256];
    pid_t pid;

    if (argc != 2) {
        fprintf(stderr,"usage: talker hostname\n");
        exit(1);
    }
    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_DGRAM;

    if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and make a socket
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,p->ai_protocol)) == -1) {
            perror("talker: socket");
            continue;
        }
        break;
    }

    if (p == NULL) {
        fprintf(stderr, "talker: failed to bind socket\n");
        return 2;
    }
    //SEND an authentication to server
    if ((numbytes = sendto(sockfd,"AUTH",5,0,p->ai_addr, p->ai_addrlen)) == -1) {
        perror("talker: sendto");
        exit(1);
    }
    if(numbytes == 0){
        printf("CLIENT FAILED TO AUTHENTICATE TO SERVER\n");
        exit(0);    

    }
    // WAIT for go signal from server
    printf("Waiting for Server Response\n");    
    if ((numbytes = recvfrom(sockfd,ok, MAXBUFLEN-1 , 0,(struct sockaddr *)&server_addr, &server_addrlen)) == -1) {
            perror("recvfrom");
            exit(1);
    }
    if(strcmp(ok,"ok")!=0){
        printf("NO SERVER RESPONSE\n");     
        exit(0);    
    }
    pid = fork();   
    if(pid>0){                      

        do {    
            printf("Enter message to send >>> ");   
            fgets(sendbuffer,sizeof(sendbuffer),stdin);
            printf("\n");
            if ((numbytes = sendto(sockfd, sendbuffer, strlen(sendbuffer)+1,0,p->ai_addr, p->ai_addrlen)) == -1) {
                perror("talker: sendto");
                exit(1);
            }

        } while(strcmp(".exit\n",sendbuffer) != 0);

    }
    else if(pid==0){
        while(1){
            if ((numbytes = recvfrom(sockfd,rcvbuffer,MAXBUFLEN-1 ,0,NULL,NULL)) == -1) {
                perror("recvfrom");
                exit(1);
            }
            printf("\nMessage Received >>>%s",rcvbuffer);
        }
    }

    freeaddrinfo(servinfo);
    close(sockfd);
    kill(pid,SIGUSR1);
    return 0;
}

I'd like to know how to determine if client 1 sent the message so I can relay it to client2 or vice versa. 我想知道如何确定客户端1是否发送了消息,以便可以将其转发给客户端2,反之亦然。 Thanks! 谢谢!

The 5th and 6th arguments to recvfrom get filled in with the address of the socket that sent the packet. recvfrom的第5和第6参数用发送数据包的套接字的地址填充。 So after you get a packet, compare that address with the addresses of your clients. 因此,在收到数据包后,将该地址与客户的地址进行比较。 That will tell you which client sent that message. 这将告诉您哪个客户端发送了该消息。

您可以创建可以存储活动连接的链表,一旦收到来自任何客户端的消息,就可以中继到所有活动客户端...

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM