5

We have six WSDLs compiled within the same project, and due to some limits of hardware we can only open one port for listening.

For doing this, we choose the approach described by chapter 7.2.8 How to Chain C++ Server Classes to Accept Messages on the Same Port in this gSOAP Manual.

However, when using this approach in we encounter many sever issues:

1. If lots of requests arrive concurrently, then sometimes soap_begin_serve reports error with error=-1, socket is closed immediately by soap server after it is established

2. If we call xxx.destory() after soap_free_stream(), then soap_accept() will report an error of bad file descriptor and not work anymore (solved)

Anybody knows what are the reasons of above phoenomenon? How to solve them?
Our code is very close to the example except a few changes, see below section.

//server thread 
Abc::soapABCService server; // generated with soapcpp2 -i -x -n -QAbc

server.bind(NULL, 12345, 100);  
server.soap_mode = SOAP_KEEP_ALIVE | SOAP_UTF_CSTRING;
server.recv_timeout = server.send_timeout = 60;

while (true)
{
    server.accept(); 

    ... 
    pthread_create(&pid, NULL, handle_new_request, server.copy());
 }  // while(true)



 // work thread - the thread function
 void *handle_new_request(void* arg)
 {
    // generated with soapcpp2 -i -x -n -QAbc 
    Abc::soapABCService *abc = (Abc::soapABCService*)arg; 
    Uvw::soapUVWService uvw; // generated with soapcpp2 -i -x -n -QUvw 
    Xyz::soapXYZService xyz; // generated with soapcpp2 -i -x -n -QXyz

    if(soap_begin_serve(abc)) 
    {
        //sometimes it reports error
        //due to unkown reason, socket was closed by soap server 
        abc->soap_stream_fault(std::cerr); 
    }
    else if (abc->dispatch() == SOAP_NO_METHOD) 
    { 
        soap_copy_stream(&uvw, abc);
        uww.state = SOAP_COPY;

        if (uvw.dispatch() == SOAP_NO_METHOD) 
        { 
            soap_copy_stream(&xyz, &uvw); 
            xyz.state = SOAP_COPY;

            if (xyz.dispatch()) 
            { 
                soap_send_fault(&xyz); // send fault to client 
                xyz.soap_stream_fault(std::cerr); 
            } 

            soap_free_stream(&xyz); // free the copy 
            xyz.destroy();
        } 
        else
        { 
            soap_send_fault(&uvw); // send fault to client 
            uvw.soap_stream_fault(std::cerr); 
        }  

        soap_free_stream(&uvw); // free the copy 
        uvw.destroy();
    }
    else if (abc->error)
    {
        abc->soap_stream_fault(std::cerr);
    }
    else
    {

    }

    abc->destroy();
    delete abc;
    abc = NULL;
 }       
Wallace
  • 561
  • 2
  • 21
  • 54
  • I noticed in your code that you are using `soap_copy_stream` from `uvw` to `xyz` even though `xyz`'s stream was already free'd. Is it okay to `soap_copy_stream` from a service that was already `soap_free_stream`'d? – ssemilla Jul 18 '15 at 11:37
  • @weavr this might be a problem, I will go checking my code – Wallace Jul 18 '15 at 14:41

1 Answers1

2

Finally I found the reason why some connections were closed by the server rightly after they were established.

It's not the gSOAP server's fault, it's because all connections were coming from a same machine, these clients were set up to reuse address and port reuse caused this problem.

Wallace
  • 561
  • 2
  • 21
  • 54