SO_REUSEADDR无法正常工作

时间:2017-02-21 21:18:04

标签: c++ c sockets networking

我有两个进程,在第一个进程(服务器)为五个客户端提供服务后,它将作业交给第二个进程。为此,我使用套接字。在进程A为特定数量的请求提供服务之后,我希望进程B在同一端口上开始为它们提供服务。 为此,我在进程A中关闭sfd并在进程B中打开它。但是,在绑定时,我遇到绑定错误:地址已经在使用错误,即使在使用SO_REUSEADDR之后。此外,我只在关闭进程A中的sfd以确保绑定成功后才调用进程B. 任何帮助是极大的赞赏。这是代码。处理代码:

#include<stdio.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<stdlib.h>
#include<unistd.h>
#include<string.h>
#include<arpa/inet.h>
#include<sys/time.h>
#include<iostream>
#include<netinet/in.h>
#include<sys/select.h>
#include<sys/shm.h>
#include<signal.h>

using namespace std;

struct shm{
    int aid;
    int sid;
    int bid;
    int cid;
    int pno;
    //int ports[4];
}*val;

int sfds[4];
int count=4;    

void func1(int a){
    fd_set rfds;
    while(1){
        FD_ZERO(&rfds);
        struct timeval timer;timer.tv_sec=0;timer.tv_usec=10;
        for(int i=0;i<count;i++){
            FD_SET(sfds[i], &rfds);
        }
        if(select(sfds[count-1]+1, &rfds, NULL, NULL, &timer)){
                for(int i=0;i<count;i++){
                    if(FD_ISSET(sfds[i], &rfds)){
                        val->pno = i;
                        close(sfds[i]);
                        // Remove the corresponding sfd                     
                        for(int j=val->pno;j<count-1;j++){
                            sfds[j] = sfds[j+1];
                        }                       
                        count--;
                        kill(val->aid, SIGUSR2);
                        if(count>0)signal(SIGUSR1, &func1);
                        else exit(1);                       
                        return;
                    }
                }
            }       
    }
}

void func2(int b){
    struct sockaddr_in cliaddr;socklen_t clilen;
    int lc=0;
    for(int i=0;i<3;i++){
        int nsfd = accept(sfds[val->pno], (struct sockaddr*)&cliaddr, &clilen);
        if(nsfd<0){perror("Error");exit(1);}
        cout<<"Connection accepted";
        send(nsfd, "OkaA", 5, 0);
        close(nsfd);
    }
    if(close(sfds[val->pno])<0){perror("Error closing");exit(1);}
    cout<<"Closed"<<endl;   
    // Remove the corresponding sfd

    for(int i=val->pno;i<count-1;i++){
        sfds[i] = sfds[i+1];
    }

    count--;

    kill(val->bid, SIGUSR1);
    if(count>0)signal(SIGUSR2, &func2);
    else exit(1);
    return;
}

int main(){
    int shmid = shmget(12345, sizeof(struct shm),  IPC_CREAT | 0666);
    if(shmid<0){perror("Error");}   
    val = (struct shm*)shmat(shmid, NULL, 0);
    //cout<<"yo2";  
    signal(SIGUSR1, &func1);
    signal(SIGUSR2, &func2);    
    for(int i=0;i<4;i++){
        //val->ports[i] = 7590+i;       
        sfds[i] = socket(AF_INET, SOCK_STREAM, 0);

        const int       optVal = 1;
        const socklen_t optLen = sizeof(optVal);

        int rtn = setsockopt(sfds[i], SOL_SOCKET, SO_REUSEADDR, (void*) &optVal, optLen);
        if(rtn<0){perror("Error");exit(1);}
        struct sockaddr_in servaddr;
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(7590+i);
        servaddr.sin_addr.s_addr = INADDR_ANY;
        if(bind(sfds[i], (struct sockaddr*)&servaddr, sizeof(servaddr))<0){perror("Error");exit(1);}
        if(listen(sfds[i],4)<0){perror("Error");exit(1);}
    }
    int c = fork();

    if(c>0){
        val->aid = c;
        val->sid = getpid();        
        kill(getpid(), SIGUSR1);
        while(1);
    }else if(c==0){
        while(1);
    }else{
        perror("Error");exit(1);
    }   

}

流程B代码:

using namespace std;

struct shm{
    int aid;
    int sid;
    int bid;
    int cid;
    int pno;
}*val;

int sfds[4];
int count=4;    

void func1(int a){

    int sfd = socket(AF_INET, SOCK_STREAM, 0);
    struct sockaddr_in servaddr;
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(7590+val->pno);
    servaddr.sin_addr.s_addr = INADDR_ANY;
    sleep(50);
    if(bind(sfd, (struct sockaddr*)&servaddr, sizeof(servaddr))<0){perror("Error");exit(1);}
    if(listen(sfd, 4)<0){
            perror("Error");exit(1);
    }
    for(int i=0;i<3;i++){
        struct sockaddr_in cliaddr;socklen_t clilen;
        int nsfd = accept(sfd, (struct sockaddr*)&cliaddr, &clilen);
        send(nsfd, "OkaB", 5, 0);
    }
    close(sfd);
    signal(SIGUSR1, &func1);
    kill(val->cid, SIGUSR1);    
}

int main(){
    signal(SIGUSR1, &func1);
    int shmid = shmget(12345, sizeof(struct shm),  IPC_CREAT | 0666);
    if(shmid<0){perror("Error");}   
    val = (struct shm*)shmat(shmid, NULL, 0);
    val->bid = getpid();    
    while(1);
}

0 个答案:

没有答案