0

I am sending data (10 files, approx 10-20 kb each) using sockets in C++ on Linux.

My pseudo code in the server:

for(i=0;i<10;i++){ ret = send(sockfd, filedata, filedatasize, 0); } 

ret returns the correct file size for all data files, no errors, but the client only receives 4-5 files.

But, if I use this instead:

for(i=0;i<10;i++){ ret = send(sockfd, filedata, filedatasize, 0); sleep(1); } 

The client receives all files, and not errors!

What is the problem?

I tried tweaking SO_RCVBUF and SO_SNDBUF, but no changes.

EDIT: (the complete code has 200000 lines to paste!)

Here is the server code:

int Socket::sendMsg(char * data, unsigned int uiSize) { unsigned short * us; int i, iRet; us = (unsigned short *)(m_pSendBuffer); *us = (unsigned short)(uiSize + 2); memcpy((char *)m_pSendBuffer + 2, data, uiSize); iRet = isend(m_pSendBuffer, uiSize + 2); if (iRet<0) { return SOCKET_ERROR; } return iRet; } int Socket::isend(char * data, int size) { int outlen, ret; outlen= 0; while (outlen< size) { ret= send(sockfd, (data+ outlen), size - outlen, 0); if (ret< 0) { return -1; } else outlen+= ret; } return outlen; } 

Here is the client code:

void XSocket::onRead() { int iRet; unsigned short * usp; unsigned int uiReadSize; while (1) { iRet = recv(m_Sock, (char *)m_pRecvBuffer, 2, 0); uiReadSize = 0; usp = (unsigned short *)(m_pRecvBuffer); uiReadSize = (int)(*usp - 2); iRet = recv(m_Sock, (char *)(m_pRecvBuffer + 2), uiReadSize, 0); if (iRet < 0) { //return error } else if (iRet == 0) { //disconnect } //PROCCESS MSG } } 
9
  • Can you show the code at the client side? Commented Jul 29, 2016 at 13:30
  • is this tcp or udp? Commented Jul 29, 2016 at 13:55
  • @FirstStep im post methods of class! im using epoll for driver events, and nonblocking Commented Jul 29, 2016 at 13:58
  • When sending, are you sure 'filedatasize' is what you expect it to be? i.e the file read has actually succeeded? Commented Jul 29, 2016 at 14:01
  • @SamerTufail yes im sure! filedatasize is the correct! Commented Jul 29, 2016 at 14:03

2 Answers 2

1

On the client side:

  1. you are not doing any error handling on the first recv() call, and your second recv() call is not breaking the loop if the server disconnects gracefully.

  2. you are not looping the reading of each buffer of data, like you loop the sending of them on the server side. There is no 1-to-1 relationship between the number of bytes sent and the number of bytes received. If you are expecting X number of bytes to arrive, keep reading until you actually receive that many bytes.

Given these bugs, there is no guarantee that your client is actually receiving all of the data correctly.

Try something more like this:

void XSocket::onRead() { int iRet; unsigned short * usp; unsigned int uiReadSize; while (1) { iRet = irecv((char *)m_pRecvBuffer, 2); if (iRet<= 0) { break; } usp = (unsigned short *)(m_pRecvBuffer); uiReadSize = (int)(*usp - 2); iRet = irecv((char *)(m_pRecvBuffer + 2), uiReadSize); if (iRet<= 0) { break; } //PROCCESS MSG } } int XSocket::irecv(char * data, int size) { int inlen, ret; inlen= 0; while (inlen< size) { ret= recv(m_Sock, (data+ inlen), size - inlen, 0); if (ret< 0) { return -1; } else if (ret== 0) { return 0; } else { inlen+= ret; } } return inlen; } 
Sign up to request clarification or add additional context in comments.

2 Comments

hi @Remy Lebeau, im coded a pseudo code, full source have 200k lines! im have contemplated 2 cases in the full code.
this solution solve for edge trigger of epoll! thanks!
0

im solved this problem!!, im changed epoll from edge trigger to level trigger, and solved!

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.