c++ - Socket doesn't receive complete data on HPUX -


i don't understand going wrong here, hope may spot missed.

i'm writing user daemon accepting client develop in java. client connects , sends username password. developed code under cygwin , there works. daemon sends introduction, client sends username , password , daemon responds either disconnecting client or sending ok (not yet done).

when test using cygwin works on localhost. ported code hpux , client can connect , receives introduction daemon. when client sends it's username , password doesn't work anymore. daemon receives 1 byte , when tries read again -1 result eagain , nothing else. client doesn't show error , on daemon side there none. when step through code gdb messages revceived completely. :(

the code use this, if more info needed can add it:

int tcpsocket::receive(socketmessage &omessage, int nbytes) {     int max = getsendbuffersize();      if(nbytes != -1 && nbytes < max)         max = nbytes;      socketmessage sb(max);     int rcv_bytes = 0;     int total = 0;     int error = 0;      while(1)     {         rcv_bytes = ::recv(getsocketid(), &sb[0], sb.size(), 0);         error = errno;         file_log(logdebug4) << "received on socket: " << msocketid << " bytes: " << rcv_bytes << "  expected:" << sb.size() << " total: " << total << " errno: " << error;          if(rcv_bytes == -1)         {             if(error == eagain || error == ewouldblock)                 return total;              throw socketexception(this, socketexception::receive, error, "socket", "client connection error!", __file__, __line__);         }          //if(rcv_bytes == 0)         //  throw socketexception(this, socketexception::receive, error, "socket", "client connection has been closed!");          total += rcv_bytes;         omessage.insert(omessage.end(), sb.begin(), sb.begin()+rcv_bytes);     }      return total; } 

the output of log this:

16:16:04.391 debug4: received on socket: 4 bytes: 1  expected:32768 total: 0 errno: 2 16:16:04.391 debug4: received on socket: 4 bytes: -1  expected:32768 total: 1 errno: 11 

so rest of 30 bytes , why not returned?

update

this part of code receives data. socket class deals raw socket without protocoll. protocol implemented in separate class. receive function supposed grab many bytes there available on network , put in buffer (socketmessage). doesn't matter if number of bytes multiple messages or part of single message, because controlling class construct actual messageblock out of (maybe) partial messagestream. first call receives 1 byte not problem, because if message not complete caller waits in loop until more data arrives , message becomes completed. since there can more 1 client i'm using non blocking sockets. didn't want deal separate threads, server multiplexing connections. problem here receive receives 1 byte while know there should more. errorcode eagain handled , when receive entered next, should more bytes. if network transmitted 1 byte, rest of message should still arrive next, doesn't. select waits on socket receive data blocks if there nothing there. when run same code in dbg , step through works. when connect again same client more bytes revceived. when use same code cygwin using localhost works fine.

update

here complete code.

main.cpp      mserversocket = new tcpsocket(getlisteningport());     mserversocket->bindsocket();     mserversocket->setsocketblocking(false);     mserversocket->listentoclient(0);      setupsignals();     while(issigterm() == false)     {         try         {             max = preparelistening();              //memset(&ts, 0, sizeof(struct timespec));             pret = pselect(max+1, &mreaders, &mwriters, &mexceptions, null, &msignalmask);             error_code = errno;             if(pret == 0)             {                 // timeout occured, not interested in now.                 // shouldn't happen anyway.                 continue;             }             processrequest(pret, error_code);          }         catch (socketexception &excp)         {             removeclientconnection(findclientconnection(excp.gettcpsocket()));         }     } // while sigterm   basesocket.cpp:  #ifdef unix      #include <sys/socket.h>     #include <sys/types.h>     #include <sys/ioctl.h>     #include <unistd.h>     #include <fcntl.h>     #include <errno.h>  #endif  #include "support/exceptions/socket_exception.h" #include "support/logging/simple_log.h" #include "support/network/base_socket.h"  using namespace std;  basesocket::basesocket(void) {     msocketid = -1;     msendbuffersize = max_send_len; }  basesocket::basesocket(int pnumber) {     msocketid = -1;     mportnumber = pnumber;     mblocking = 1;     msendbuffersize = max_send_len;      try     {         if ((msocketid = ::socket(af_inet, sock_stream, 0)) == -1)         { #ifdef unix             throw socketexception(this, socketexception::constructor, errno, "socket", "unix: error in socket constructor", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     }      /*      set initial address of client shall communicated      address long using same port number.      clientaddr structure used in future storing actual      address of client applications communication going      start      */     mclientaddr.sin_family = af_inet;     mclientaddr.sin_addr.s_addr = htonl(inaddr_any);     mclientaddr.sin_port = htons(mportnumber);     updatesendbuffersize(max_send_len); }  void basesocket::updatesendbuffersize(int nnewsize) {     msendbuffersize = getsendbuffersize();     if(msendbuffersize > nnewsize)         msendbuffersize = nnewsize; }  basesocket::~basesocket(void) {     close(); }  void basesocket::setsocketid(int socketfd) {     msocketid = socketfd; }  int basesocket::getsocketid() {     return msocketid; }  // returns port number int basesocket::getportnumber() {     return mportnumber; }  void basesocket::setdebug(int debugtoggle) {     try     {         if (setsockopt(msocketid, sol_socket, so_debug, (char *) &debugtoggle, sizeof(debugtoggle)) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error set debug", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     } }  void basesocket::setreuseaddr(int reusetoggle) {     try     {         if (setsockopt(msocketid, sol_socket, so_reuseaddr, (char *) &reusetoggle,               sizeof(reusetoggle)) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error set reuse address", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     } }  void basesocket::setkeepalive(int alivetoggle) {     try     {         if (setsockopt(msocketid, sol_socket, so_keepalive, (char *) &alivetoggle,               sizeof(alivetoggle)) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error set keep alive", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     } }  void basesocket::setlingerseconds(int seconds) {     struct linger lingeroption;      if (seconds > 0)     {         lingeroption.l_linger = seconds;         lingeroption.l_onoff = 1;     }     else         lingeroption.l_onoff = 0;      try     {         if (setsockopt(msocketid, sol_socket, so_linger, (char *) &lingeroption,               sizeof(struct linger)) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error set linger seconds", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     } }  void basesocket::setlingeronoff(bool lingeron) {     struct linger lingeroption;      if (lingeron)         lingeroption.l_onoff = 1;     else         lingeroption.l_onoff = 0;      try     {         if (setsockopt(msocketid, sol_socket, so_linger, (char *) &lingeroption,               sizeof(struct linger)) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error set linger on/off", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     } }  void basesocket::setsendbuffersize(int sendbufsize) {     if (setsockopt(msocketid, sol_socket, so_sndbuf, (char *) &sendbufsize, sizeof(sendbufsize)) == -1)     { #ifdef unix         throw socketexception(this, socketexception::option, errno, "socket", "unix: error send buffer size", __file__, __line__); #endif     }     updatesendbuffersize(sendbufsize); }  void basesocket::setreceivebuffersize(int receivebufsize) {     if (setsockopt(msocketid, sol_socket, so_rcvbuf, (char *) &receivebufsize, sizeof(receivebufsize)) == -1)     { #ifdef unix         throw socketexception(this, socketexception::option, errno, "socket", "unix: error set receive buffer size", __file__, __line__); #endif     } }  int basesocket::issocketblocking() {     return mblocking; }  void basesocket::setsocketblocking(int blockingtoggle) {     if (blockingtoggle)     {         if (issocketblocking())             return;         else             mblocking = 1;     }     else     {         if (!issocketblocking())             return;         else             mblocking = 0;     }      try     { #ifdef unix         int flags;         if (-1 == (flags = fcntl(msocketid, f_getfl, 0)))             flags = 0;          if(mblocking)             fcntl(msocketid, f_setfl, flags & (~o_nonblock));         else             fcntl(msocketid, f_setfl, flags | o_nonblock);          /*if (ioctl(socketid, fionbio, (char *) &blocking) == -1)         {             throw socketexception(this, socketexception::option, errno, "socket", "unix: error set socke blocking");         }*/ #endif     }     catch (socketexception& excp)     {         excp.response();     } }  int basesocket::getdebug() {     int myoption;     int myoptionlen = sizeof(myoption);      try     {         if (getsockopt(msocketid, sol_socket, so_debug, (void *) &myoption, &myoptionlen) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error debug", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();         return -1;     }      return myoption; }  int basesocket::getreuseaddr() {     int myoption;     int myoptionlen = sizeof(myoption);      try     {         if (getsockopt(msocketid, sol_socket, so_reuseaddr, (void *) &myoption, &myoptionlen) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error reuse address", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();         return -1;     }      return myoption; }  int basesocket::getkeepalive() {     int myoption;     int myoptionlen = sizeof(myoption);      try     {         if (getsockopt(msocketid, sol_socket, so_keepalive, (void *) &myoption, &myoptionlen) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error keep alive", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();         return -1;     }     return myoption; }  int basesocket::getlingerseconds() {     struct linger lingeroption;     int myoptionlen = sizeof(struct linger);      try     {         if (getsockopt(msocketid, sol_socket, so_linger, (void *) &lingeroption, &myoptionlen) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error linger seconds", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();         return -1;     }      return lingeroption.l_linger; }  bool basesocket::getlingeronoff() {     struct linger lingeroption;     int myoptionlen = sizeof(struct linger);      try     {         if (getsockopt(msocketid, sol_socket, so_linger, (void *) &lingeroption, &myoptionlen) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error linger on/off", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     }      if (lingeroption.l_onoff == 1)         return true;     else         return false; }  int basesocket::getsendbuffersize() {     int sendbuf;     int myoptionlen = sizeof(sendbuf);      try     {         if (getsockopt(msocketid, sol_socket, so_sndbuf, (void *)&sendbuf, &myoptionlen) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error send buffer size", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();         return -1;     }     return sendbuf; }  int basesocket::getreceivebuffersize() {     int rcvbuf;     int myoptionlen = sizeof(rcvbuf);      try     {         if (getsockopt(msocketid, sol_socket, so_rcvbuf, (void *) &rcvbuf, &myoptionlen) == -1)         { #ifdef unix             throw socketexception(this, socketexception::option, errno, "socket", "unix: error receive buffer size", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();         return -1;     }     return rcvbuf; }  ostream &operator<<(ostream& io, basesocket& s) {     string flagstr = "";      io << endl;     io << "summary of socket settings:" << endl;     io << "   socket id:     " << s.getsocketid() << endl;     io << "   port #:        " << s.getportnumber() << endl;     io << "   debug:         " << (flagstr = s.getdebug() ? "true" : "false")           << endl;     io << "   reuse addr:    " << (flagstr = s.getreuseaddr() ? "true" : "false")           << endl;     io << "   keep alive:    " << (flagstr = s.getkeepalive() ? "true" : "false")           << endl;     io << "   send buf size: " << s.getsendbuffersize() << endl;     io << "   recv bug size: " << s.getreceivebuffersize() << endl;     io << "   blocking:      "           << (flagstr = s.issocketblocking() ? "true" : "false") << endl;     io << "   linger on:     "           << (flagstr = s.getlingeronoff() ? "true" : "false") << endl;     io << "   linger seconds: " << s.getlingerseconds() << endl;     io << endl;     return io; }  void basesocket::close(void) {     ::close(msocketid); }  tcpsocket.cpp:   #ifdef unix     #include <sys/socket.h>     #include <sys/types.h>     #include <sys/ioctl.h>     #include <unistd.h>     #include <fcntl.h>     #include <errno.h> #endif  #include <sstream>  #include "support/logging/log.h" #include "support/exceptions/socket_exception.h" #include "support/logging/simple_log.h" #include "support/network/tcp_socket.h"  using namespace std;  const int msg_header_len = 6;  tcpsocket::tcpsocket() : basesocket() { }  tcpsocket::tcpsocket(int portid) : basesocket(portid) { }  tcpsocket::~tcpsocket() { }  void tcpsocket::initialize() { }  void tcpsocket::bindsocket() {     try     {         if (bind(msocketid, (struct sockaddr *) &mclientaddr, sizeof(struct sockaddr_in)) == -1)         { #ifdef unix             throw socketexception(this, socketexception::bind, 0, "socket", "unix: error calling bind()", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     } }  void tcpsocket::connecttoserver(string& servernameoraddr, hosttype htype) {     /*       when method called, client socket has been built already,      have socketid , portnumber ready.       hostinfo instance created, no matter how server's name      given (such www.yuchen.net) or server's address given (such      169.56.32.35), can use hostinfo instance      ip address of server      */      hostinfo serverinfo(servernameoraddr, htype);      // store ip address , socket port number     struct sockaddr_in serveraddress;      serveraddress.sin_family = af_inet;     serveraddress.sin_addr.s_addr = inet_addr(           serverinfo.gethostipaddress().c_str());     serveraddress.sin_port = htons(mportnumber);      // connect given address     try     {         if (connect(msocketid, (struct sockaddr *) &serveraddress, sizeof(serveraddress)) == -1)         { #ifdef unix             throw socketexception(this, socketexception::connect, 0, "socket", "unix: error calling connect()", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     } }  tcpsocket *tcpsocket::acceptclient(string& clienthost) {     int newsocket; // new socket file descriptor returned accept system call      // length of client's address     int clientaddresslen = sizeof(struct sockaddr_in);     struct sockaddr_in clientaddress;    // address of client sent data      // accepts new client connection , stores socket file descriptor     try     {         if ((newsocket = accept(msocketid, (struct sockaddr *) &clientaddress, &clientaddresslen)) == -1)         { #ifdef unix             throw socketexception(this, socketexception::accept, 0, "socket", "unix: error calling accept()", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();         return null;     }      // host name given address     char *saddress = inet_ntoa((struct in_addr) clientaddress.sin_addr);     hostinfo clientinfo(saddress, address);     clienthost += clientinfo.gethostname();      // create , return new tcpsocket object     tcpsocket* retsocket = new tcpsocket();     retsocket->setsocketid(newsocket);     return retsocket; }  void tcpsocket::listentoclient(int totalnumports) {     try     {         if (listen(msocketid, totalnumports) == -1)         { #ifdef unix             throw socketexception(this, socketexception::listen, 0, "socket", "unix: error calling listen()", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     } }  ostream &operator<<(ostream &ostream, const tcpsocket &osocket) {     ostream << osocket.msocketid;     return ostream; }  int tcpsocket::send(socketmessage const &obuffer, int nsize) {     int numbytes;  // number of bytes sent     int error = errno;      if(nsize == -1)         nsize = obuffer.size();      if((unsigned int)nsize > obuffer.size())     {         std::stringstream ss;         ss << "invalid buffersize! requested: " << (unsigned int)nsize << " provided: " << obuffer.size();         std::string s;         ss >> s;         file_log(logerror) << s;         throw socketexception(this, socketexception::send, 0, "socket", s, __file__, __line__);     }      // sends message connected host     try     {         file_log(logdebug4) << "sending on socket: "<< msocketid << " bytes:" << nsize;         numbytes = ::send(msocketid, &obuffer[0], nsize, 0);         error = errno;         file_log(logdebug4) << "sent on socket: "<< msocketid << " bytes:" << nsize << " errno: " << error;         if(numbytes == -1)         { #ifdef unix             if(error == eagain || error == ewouldblock)             {                 return -1;             }             else                 throw socketexception(this, socketexception::send, error, "socket", "unix: error calling send()", __file__, __line__); #endif         }     }     catch (socketexception& excp)     {         excp.response();     }      return numbytes; }  int tcpsocket::receive(socketmessage &omessage, int nbytes) {     int max = getsendbuffersize();      if(nbytes != -1 && nbytes < max)         max = nbytes;      socketmessage sb(max);     int rcv_bytes = 0;     int total = 0;     int error = 0;      while(1)     {         rcv_bytes = ::recv(getsocketid(), &sb[0], sb.size(), 0);         error = errno;         file_log(logdebug4) << "received on socket: " << getsocketid() << " bytes: " << rcv_bytes << "  expected:" << sb.size() << " total: " << total << " errno: " << error;          if(rcv_bytes == -1)         {             if(error == eagain || error == ewouldblock)                 return total;              throw socketexception(this, socketexception::receive, error, "socket", "client connection error!", __file__, __line__);         }          // socket has been closed.         if(rcv_bytes == 0)             return total;          total += rcv_bytes;         omessage.insert(omessage.end(), sb.begin(), sb.begin()+rcv_bytes);     }      return total; }  void tcpsocket::close(void) {     basesocket::close(); } 

are sure nagle algorithm isn't kicking in here? if haven't disabled setting tcp_nodelay socket option data may not sent until amount of data (mss) available.


Comments

Popular posts from this blog

jquery - How can I dynamically add a browser tab? -

node.js - Getting the socket id,user id pair of a logged in user(s) -

keyboard - C++ GetAsyncKeyState alternative -