首页 > 解决方案 > TCP 客户端连接到两个 TCP 服务器

问题描述

这是其中一个 TCP 服务器的代码(它也是一个 UDP 客户端,但这不重要),我们称之为 FS

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>


int max(int fd, int fd2){
    if(fd > fd2) return fd;
    else return fd2;

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

    int ASfd, errcode, listenfd, User_fd;
    ssize_t n;
    socklen_t addrlen, addrlen2;
    struct addrinfo hints, hints2, *res, *res2;
    struct sockaddr_in addr;
    struct sockaddr_in addr2;
    fd_set readfds;

    int pid;

    char* AS_PORT = argv[3];
    char* AS_IP = argv[2];
    char* FS_PORT = argv[1];
    char buffer[364];
    char check[4],  num_aluno[6],  Fname[64],  Fcontent[128]; 
    long Fsize;

    //TCP SOCKET
    listenfd = socket(AF_INET,SOCK_STREAM,0);
    if(listenfd == -1) exit(1);

    memset(&hints2,0,sizeof hints2);
    hints2.ai_family=AF_INET;
    hints2.ai_socktype=SOCK_STREAM;
    hints2.ai_flags=AI_PASSIVE;

    errcode = getaddrinfo(NULL,FS_PORT,&hints2,&res2);
    if(errcode != 0){
        perror("getaddrinfo");
        exit(1);
    }

    n=bind(listenfd,res2->ai_addr, res2->ai_addrlen);
    if(n==-1) exit(1);

    if(listen(listenfd,10) == -1) exit(1);

    ASfd = socket(AF_INET,SOCK_DGRAM,0);
    if(ASfd==-1) exit(1);

    memset(&hints,0,sizeof hints);
    hints.ai_family=AF_INET;
    hints.ai_socktype=SOCK_DGRAM;
    hints.ai_flags=AI_PASSIVE;

    errcode = getaddrinfo(AS_IP,AS_PORT,&hints,&res);
    if(errcode != 0) exit(1);

    addrlen=sizeof(addr);
    addrlen2=sizeof(addr2);


    while(1){
        FD_CLR(ASfd,&readfds);
        FD_CLR(listenfd,&readfds);
        FD_SET(ASfd,&readfds);
        select(max(ASfd,listenfd)+1,&readfds,NULL,NULL,NULL);
        if(FD_ISSET(ASfd,&readfds)){
            n = recvfrom(ASfd,buffer,128,0,(struct sockaddr*)&addr,&addrlen);
            if(n == -1) exit(1);
            write(1,buffer,strlen(buffer)+1);
        }
        else if(FD_ISSET(listenfd,&readfds)){
            User_fd = accept(listenfd,(struct sockaddr*)&addr2,&addrlen2);
            if(User_fd == -1){
                perror("accept");
                exit(1);
            }            
            if ((pid = fork())==0) {
                close(listenfd);
                while(1){
                    read(User_fd,buffer,364);
                    write(1,buffer,strlen(buffer)+1);
                    sscanf(buffer,"%s",check);
                    if(strcmp(check,"UPL")==0){
                        sscanf(buffer,"%s %s %s %ld %s",check,num_aluno,Fname,&Fsize,Fcontent);
                        write(1,Fcontent,strlen(Fcontent)+1);
                    }
                }
                freeaddrinfo(res);
                close(User_fd);
                exit(0);
            }
        }
    }

}

这是我们的第二个 TCP 服务器(它也是一个 UDP 服务器)的代码,我们称之为 AS

int main(){
    int fd, errcode, listenfd, newfd;
    ssize_t n;
    socklen_t addrlen, addrlen2;
    struct addrinfo hints, hints2, *res, *res2;
    struct sockaddr_in addr;
    struct sockaddr_in addr2;
    char buffer[128], buffertroll[128];
    fd_set readfds;
    int status = 0, rid, vc, new_vc = 0, pid, tid;

    char Fop;
    char check[4], password[9], num_aluno_s[6], PD_IP[64], PD_PORT[6], path[64], Fname[64];

    //TCP SOCKET
    listenfd = socket(AF_INET,SOCK_STREAM,0);
    if(listenfd == -1) exit(1);

    memset(&hints2,0,sizeof hints2);
    hints2.ai_family=AF_INET;
    hints2.ai_socktype=SOCK_STREAM;
    hints2.ai_flags=AI_PASSIVE;

    errcode = getaddrinfo(NULL,PORT,&hints2,&res2);
    if(errcode != 0) exit(1);

    n=bind(listenfd,res2->ai_addr, res2->ai_addrlen);
    if(n==-1) exit(1);

    if(listen(listenfd,10) == -1) exit(1);

    //UDP SOCKET (PD)
    fd = socket(AF_INET,SOCK_DGRAM,0);
    if(fd==-1) exit(1);

    memset(&hints,0,sizeof hints);
    hints.ai_family=AF_INET;
    hints.ai_socktype=SOCK_DGRAM;
    hints.ai_flags=AI_PASSIVE;

    errcode = getaddrinfo(NULL,PORT,&hints,&res);
    if(errcode != 0) exit(1);

    n=bind(fd,res->ai_addr, res->ai_addrlen);
    if(n==-1) exit(1);


    mkdir("Users",0777);

    addrlen=sizeof(addr);
    addrlen2=sizeof(addr2);

    while(1){
        FD_CLR(fd,&readfds);
        FD_SET(fd,&readfds);
        FD_SET(listenfd,&readfds);
        select(max(fd,listenfd)+1,&readfds,NULL,NULL,NULL);
        
        /* PD communication */
        if(FD_ISSET(fd,&readfds)){
            memset(buffer,0,128);
            memset(check,0,4);
            n=recvfrom(fd,buffer,128,0,(struct sockaddr*)&addr,&addrlen);
            if(n==-1) exit(1);
            write(1,buffer,strlen(buffer)+1);

            sscanf(buffer,"%s %s %s %s %s",check,num_aluno_s,password,PD_IP,PD_PORT);

            /* case "register" message */
            if(strcmp(check,"REG")==0){
                write(1,"PD: new user, UID=",19);
                write(1,num_aluno_s,6);
                write(1,"\n",1);

                sprintf(path,"Users/%s",num_aluno_s);
                mkdir(path,0777);

                createPassFile(num_aluno_s,password);
                createRegFile(num_aluno_s,PD_IP,PD_PORT);
                
                n = sendto(fd,"RRG OK\n",8,0,(struct sockaddr*)&addr,addrlen);
                if(n == -1)  exit(1);
            }
            
            /* case "exit" message */ 
            if(strcmp(check,"UNR")==0){
                sscanf(buffer,"%s %s %s",check,num_aluno_s,password);
                memset(buffer,0,128);
                status = deleteUser(num_aluno_s, password);
                if (status) sprintf(buffer, "RUN OK\n");
                else        sprintf(buffer, "RUN NOK\n");
                n = sendto(fd,buffer,strlen(buffer)+1,0,(struct sockaddr*)&addr,addrlen);
                if(n == -1)  exit(1);
            }
        }
        /* User communication */
        else if(FD_ISSET(listenfd,&readfds)){
            newfd = accept(listenfd,(struct sockaddr*)&addr2,&addrlen2);
            if(newfd == -1){
                perror("accept");
                exit(1);
            }            
            if ((pid = fork())==0) {

                close(listenfd);
                while(1) {
                    memset(buffer,0,128);
                    memset(check,0,4);
                    read(newfd,buffer,128);
                    write(1,buffer,strlen(buffer)+1);

                    sscanf(buffer,"%s",check);
                    if(strcmp(check,"LOG")==0){
                        sscanf(buffer,"%s %s %s",check,num_aluno_s,password);
                        memset(buffer,0,128);
                        status = verifyUser(num_aluno_s, password);
                        if (status == 1){
                            sprintf(buffer,"User: login ok, UID=%s",num_aluno_s);
                            write(1,buffer,strlen(buffer)+1);
                            memset(buffer,0,128);
                            sprintf(buffer, "RLO OK\n");
                            createLogFile(num_aluno_s);   
                        }  
                        else if (status == 0) sprintf(buffer, "RLO NOK\n");
                        else                  sprintf(buffer, "ERR\n");
                        write(newfd,buffer,strlen(buffer)+1);
                    }
                    else if (strcmp(check,"REQ")==0){
                        sscanf(buffer,"%s %s %d %c %s",check,num_aluno_s,&rid,&Fop,Fname);
                        memset(buffer,0,128);
                        status = verifyLogin(num_aluno_s);
                        if (status) {
                            new_vc = getVC();
                            if (Fop == 'R' || Fop == 'U' || Fop == 'D') {
                                sprintf(buffer,"VLC %s %04d %c %s\n", num_aluno_s, new_vc, Fop, Fname);
                                sprintf(buffertroll,"User: upload req, UID=%s file: %s, RID=%d VC=%04d\n",num_aluno_s,Fname,rid,new_vc);
                                write(1,buffertroll,strlen(buffertroll)+1);
                                if (sendto(fd,buffer,strlen(buffer)+1,0,(struct sockaddr*)&addr,addrlen) == -1){
                                    write(newfd,"RRQ EPD\n",9);
                                }
                            }
                            else if (Fop == 'L' || Fop == 'X') {
                                sprintf(buffer,"VLC %s %04d %c\n", num_aluno_s, new_vc, Fop);
                                if (sendto(fd,buffer,strlen(buffer)+1,0,(struct sockaddr*)&addr,addrlen) == -1)
                                    write(newfd,"RRQ EPD\n",9);                        
                            }
                            else write(newfd,"RRQ EFOP\n",10);
                        } else write(newfd,"RRQ ELOG\n",10);
                    }
                    else if (strcmp(check,"AUT")==0){
                        sscanf(buffer,"%s %s %d %d", check, num_aluno_s, &rid, &vc);
                        if (new_vc == vc){
                            tid = getVC();
                            memset(buffertroll,0,128);
                            sprintf(buffertroll,"User: UID=%s %c, %s, TID=%04d\n",num_aluno_s,Fop,Fname,tid);
                            write(1,buffertroll,strlen(buffertroll)+1);
                            memset(buffertroll,0,128);
                            sprintf(buffertroll,"RAU %04d\n",tid);
                            write(newfd,buffertroll,strlen(buffertroll)+1);
                            createTIDFile(Fop,Fname,tid,num_aluno_s);
                        }
                    }
                    else if(strcmp(check,"EXT")==0){
                        memset(buffertroll,0,128);
                        if(deleteLogFile(num_aluno_s)==0){
                            write(newfd,"EXT NOK\n",8);
                            continue;    
                        }
                        deleteTIDFile(num_aluno_s);
                        write(newfd,"EXT OK\n",7);
                        break;
                    }
                    

                }
                freeaddrinfo(res);
                close(newfd);
                exit(0);
            }
        }
        memset(num_aluno_s,0,6);
        memset(password,0,9);
    }

    freeaddrinfo(res);
    close(fd);
    return 0;
}

这是用于连接到两个 TCP 服务器的代码

    //AS Connection
    fd = socket(AF_INET,SOCK_STREAM,0);
    if(fd==-1) exit(1);

    memset(&hints,0,sizeof hints);
    hints.ai_family=AF_INET;
    hints.ai_socktype=SOCK_STREAM;

    errcode = getaddrinfo(AS_IP,AS_PORT,&hints,&res);
    if(errcode != 0) exit(1);

    n = connect(fd,res->ai_addr,res->ai_addrlen);
    if(n==-1) exit(1);

    //FS Connection
    FSfd = socket(AF_INET,SOCK_STREAM,0);
    if(FSfd==-1) exit(1);

    memset(&hints2,0,sizeof hints2);
    hints2.ai_family=AF_INET;
    hints2.ai_socktype=SOCK_STREAM;

    errcode = getaddrinfo(FS_IP,FS_PORT,&hints2,&res2);
    if(errcode != 0){
        perror("lmao");
        exit(1);
    }

    n = connect(FSfd,res2->ai_addr,res2->ai_addrlen);
    if(n==-1) exit(1);

现在我们的客户端在 AS 上运行良好,但我们无法与 FS 连接(accept 从不接受任何连接并且它被阻止在那里),我无法弄清楚我做错了什么。

标签: csocketstcp

解决方案


FS Code需要是这样的

#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <errno.h>


int max(int fd, int fd2){
    if(fd > fd2) return fd;
    else return fd2;

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

    int ASfd, errcode, listenfd, User_fd;
    ssize_t n;
    socklen_t addrlen, addrlen2;
    struct addrinfo hints, hints2, *res, *res2;
    struct sockaddr_in addr;
    struct sockaddr_in addr2;
    fd_set readfds;

    int pid;

    char* AS_PORT = argv[3];
    char* AS_IP = argv[2];
    char* FS_PORT = argv[1];
    char buffer[364];
    char check[4],  num_aluno[6],  Fname[64],  Fcontent[128]; 
    long Fsize;

    //TCP SOCKET
    listenfd = socket(AF_INET,SOCK_STREAM,0);
    if(listenfd == -1) exit(1);

    memset(&hints2,0,sizeof hints2);
    hints2.ai_family=AF_INET;
    hints2.ai_socktype=SOCK_STREAM;
    hints2.ai_flags=AI_PASSIVE;

    errcode = getaddrinfo(NULL,FS_PORT,&hints2,&res2);
    if(errcode != 0){
        perror("getaddrinfo");
        exit(1);
    }

    n=bind(listenfd,res2->ai_addr, res2->ai_addrlen);
    if(n==-1) exit(1);

    if(listen(listenfd,10) == -1) exit(1);

    ASfd = socket(AF_INET,SOCK_DGRAM,0);
    if(ASfd==-1) exit(1);

    memset(&hints,0,sizeof hints);
    hints.ai_family=AF_INET;
    hints.ai_socktype=SOCK_DGRAM;
    hints.ai_flags=AI_PASSIVE;

    errcode = getaddrinfo(AS_IP,AS_PORT,&hints,&res);
    if(errcode != 0) exit(1);

    addrlen=sizeof(addr);
    addrlen2=sizeof(addr2);


    while(1){
        FD_CLR(ASfd,&readfds);
        FD_CLR(listenfd,&readfds);
        FD_SET(ASfd,&readfds);
        FD_SET(listenfd,&readfds);
        select(max(ASfd,listenfd)+1,&readfds,NULL,NULL,NULL);
        if(FD_ISSET(ASfd,&readfds)){
            n = recvfrom(ASfd,buffer,128,0,(struct sockaddr*)&addr,&addrlen);
            if(n == -1) exit(1);
            write(1,buffer,strlen(buffer)+1);
        }
        else if(FD_ISSET(listenfd,&readfds)){
            User_fd = accept(listenfd,(struct sockaddr*)&addr2,&addrlen2);
            if(User_fd == -1){
                perror("accept");
                exit(1);
            }            
            if ((pid = fork())==0) {
                close(listenfd);
                while(1){
                    read(User_fd,buffer,364);
                    write(1,buffer,strlen(buffer)+1);
                    sscanf(buffer,"%s",check);
                    if(strcmp(check,"UPL")==0){
                        sscanf(buffer,"%s %s %s %ld %s",check,num_aluno,Fname,&Fsize,Fcontent);
                        write(1,Fcontent,strlen(Fcontent)+1);
                    }
                }
                freeaddrinfo(res);
                close(User_fd);
                exit(0);
            }
        }
    }

推荐阅读