c++ - 共享内存仅在第一次起作用

标签 c++ c networking

我正在使用共享内存在进程之间传递值。它第一次工作,但是当我尝试再次更改它时,该值没有反射(reflect)在其他进程中。首先进程 A 更改值并发出信号 B。它使用它并将控制权传回给 A。然后 A 再次更改值,但这个新值没有反射(reflect)在进程 B 中。

//文件 1

#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 portno;
    int pno;
//int ports[4];
}*val;
int ports[4];
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;
                    val->portno = ports[i];
                    cout << "port number:" << val->portno << endl;
                    close(sfds[i]);
                    // Remove the corresponding sfd                     
                    for (int j = i; j < count - 1; j++)
                    {
                        sfds[j] = sfds[j + 1];
                        ports[j] = ports[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 < 1; 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];
        ports[i] = ports[i + 1];
    }

    count--;
    cout << " val->portnumber " << val->portno << endl;

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

int main()
{
    int shmid = shmget(123456, 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);
        ports[i] = 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], 1) < 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);
    }

}

//文件 2

#include<stdio.h>
#include<signal.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>

using namespace std;

struct shm
{
    int aid;
    int sid;
    int bid;
    int cid;
    int pno;
    int portno;
}*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->portno);
    servaddr.sin_addr.s_addr = INADDR_ANY;
    const int optVal = 1;
    const socklen_t optLen = sizeof(optVal);
    cout << val->portno << " vpn " << endl;
    int rtn = setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, (void*) &optVal,
            optLen);

    while (bind(sfd, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0)
    {
        perror("Error");
    }
    cout << endl << "Done" << endl;
    if (listen(sfd, 1) < 0)
    {
        perror("Error");
        exit(1);
    }
    for (int i = 0; i < 1; 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(123456, sizeof(struct shm), IPC_CREAT | 0666);
    if (shmid < 0)
    {
        perror("Error");
    }
    val = (struct shm*) shmat(shmid, NULL, 0);
    val->bid = getpid();
    while (1)
        ;
}

最佳答案

问题可能来自于struct shm定义:

在文件 1 中

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

在其他文件中:

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

pnoportno 不在同一位置。

正如 LP 所指出的,只有一个进程应该创建共享内存 (IPC_CREAT)

关于c++ - 共享内存仅在第一次起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/42387049/

相关文章:

c++ - 在矩形上居中文本不起作用

c - 在 C 中输入日期作为字符,无法弄清楚如何避免/

java - 如何让 jersey 和 @webservlet 一起工作

c - FIN扫描程序设计难点

c++ - Qt5:派生QQuickWidget以获取小部件

c++ - 复制构造函数和 operator=(多个数组...)

c++ - boost::buffer 和 boost::async_write

c - 文件输入 int 字符串 c

c - GtkEntry 和 "editing_done"信号

java - 如何手动启用 LibGDX 网络?