1

我正在做一个使用套接字的应用程序,所以我将套接字句柄保存在一个数组中。我有以下代码:

while(0 == 0){
    int * tx = (int*)(malloc((nr_con + 2) * sizeof(int)));
    if (conexiuni != NULL)
    {
        syslog(LOG_NOTICE,"Ajung la eliberare %d",nr_con);
        memcpy(&tx[0],&conexiuni[0],(sizeof(int) * (nr_con)));
        syslog(LOG_NOTICE,"Ajung la eliberare %d",nr_con);
        free(conexiuni);
    }
    conexiuni = tx;

    syslog(LOG_NOTICE,"Ajung la mama %d",nr_con);
    //The line bellow causes a segfault at second connection
    if ((conexiuni[nr_con] = accept(hsock,(sockaddr*)(&sadr),&addr_size)) != -1)
    {
        nr_con++;
        syslog(LOG_NOTICE,"Primesc de la %s",inet_ntoa(sadr.sin_addr));
        syslog(LOG_NOTICE,"kkt %d",conexiuni[nr_con - 1]);
        int * sz = (int*)malloc(sizeof(int));
        *sz = conexiuni[nr_con - 1];
        syslog(LOG_NOTICE,"after %d",*sz);
        pthread_create(&tidi,0,&ConexiuniHandler, sz);
    }
}

当我分配数组时第二次连接时,程序崩溃。我究竟做错了什么?我在 Windows 上尝试了相同的代码,它运行良好,但在 Linux 上它崩溃了。

4

2 回答 2

4

使用std::vector.

封装动态大小数组的序列容器。

于 2012-09-15T15:40:51.483 回答
2

我假设您想要做的是拥有一个接受连接的服务器,然后当连接被接受时,您启动一​​个线程来处理该连接请求。因此,每次您执行接受时,您都希望启动一个线程并为其提供套接字句柄。您还要跟上数组中的所有套接字句柄,当您接受新的连接请求时,该句柄会动态增加。

以下是建议的方法。我没有做任何测试,也没有编译这个代码段,但它是一个开始的地方。我正在做的一件事是每次调整数组大小时,将套接字句柄数组增加 16 个块。我这样做是因为它可以使内存管理器的工作更容易一些,并通过减少对malloc().

int nr_con = 0;      // we start off with no connections
int block_con = 16;  // number of blocks to allocate each time we increase the array
SOCKET  *conexiuni = malloc ((nr_con + block_con) * sizeof(SOCKET));
while(1) {
    syslog (LOG_NOTICE, "Ajung la mama %d", nr_con);

    // wait for a connection request to come in.  if it does, log the request
    // then create a thread to handle the request providing the socket to the thread.
    // we are keeping an array of the sockets that is dynamically increased so
    // we will allocate blocks of 16 at a time as we lengthen the array.
    if ((conexiuni[nr_con] = accept (hsock, (sockaddr*)(&sadr), &addr_size)) != -1)
    {
        block_con--;
        if (block_con < 1) {
        {
            // so lets add another block to our array by allocating the memory
            // then copying the current array to the new memory area then freeing
            // the old memory area which is no longer needed.
            block_con = 16;
            SOCKET *pTemp = malloc(nr_con + block_con) * sizeof(SOCKET));
            syslog (LOG_NOTICE, "Ajung la eliberare %d", nr_con);
            memcpy (pTemp, conexiuni, (sizeof(SOCKET) * (nr_con + 1)));
            syslog (LOG_NOTICE, "Ajung la eliberare %d", nr_con);
            free (conexiuni);
            conexiuni = pTemp;
        }
        syslog (LOG_NOTICE, "Primesc de la %s", inet_ntoa(sadr.sin_addr));
        syslog (LOG_NOTICE, "kkt %d", conexiuni[nr_con]);

        SOCKET  *sz = conexiumi + nr_con;
        syslog (LOG_NOTICE, "after %d", *sz);

        // start the thread which is to service this connection request.
        pthread_create (&tidi, 0, &ConexiuniHandler, sz);
        nr_con++;
    }
}

但是,这样的事情有一些问题。malloc()首先,在上面的示例中,由于无法提供内存请求,我没有处理内存不足错误应该返回 NULL 指针。

第二个问题是在动态扩展数组之前线程可能不会访问指向套接字的指针,从而导致提供的指针无效,因为它在动态重新分配期间被释放。因此,如果您有很多连接很快进入,这可能是一个问题。至少,线程应该做的第一件事是制作套接字句柄的本地副本。

另一个问题是您将如何返回数组以确定哪些套接字仍然有效且打开,哪些套接字在连接关闭时是陈旧的。您是否只是在连接请求进入时动态分配空间,直到服务器启动并运行几天后内存不足?

而不是使用 int,你真的应该使用 SOCKET,因为它是实际的数据类型。我意识到在大多数情况下,SOCKET 实际上是一个 int,但是在这些问题上通常最好是精确的。

于 2012-09-15T16:27:51.350 回答