TCP Sockt OLD DATA in recv buf nevr clears [SLVD?]

Discuss the development of new homebrew software, tools and libraries.

Moderators: cheriff, TyRaNiD

KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

TCP Sockt OLD DATA in recv buf nevr clears [SLVD?]

Post by KickinAezz »

Hello,

I use this to read the replies from server:

Code: Select all

 numhold=recv(sockfd,&recvbuff,255,MSG_DONTWAIT);
          if (numhold!=-1 && numhold!=0)
            {
              pspDebugScreenClear();
              pput("Reply: '%s'\n",recvbuff);
            }
The problem is after some times the recieved data gets stacked and shows up in new replies... NEVER CLEARS! Any idea why?

The server only sends back what's shown on screen at the last line; But psp shows what was just sent by server + old data recieved from server not just what it recieved the last.


KINDLY test this please, instructions inside.
http://www.sendspace.com/file/wjf1jn
Connect to server and HOLD SQUARE and wait until you see multiple Hello's.


Is there any function to 'flush' old data or buffer?


ALSO the other problem is, when this happens FRAME RATE becomes UNSTABLE
Last edited by KickinAezz on Wed Aug 13, 2008 1:18 am, edited 8 times in total.
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
SANiK
Posts: 29
Joined: Tue Jul 05, 2005 5:25 am

Post by SANiK »

1) How many times per 1 second do you call recv?
Calling it too much DDoSes the PSP's wifi from inside out - causing data to lag. This is not a problem if recv is blocking, but due to the MSG_DONTWAIT flag, it might be calling it constantly

Use a counter like so:

Code: Select all

unsigned int system_getTicks()
{
  u64 ticks; 
  sceRtcGetCurrentTick(&ticks); 
  return ticks/1000; 
}

unsigned int main(...)
{
  unsigned int startTime=system_getTicks();
  unsigned int calls=0;
  while(1)
  {
     recv();
     calls++;
     unsigned int currentTime=system_getTicks();
     if&#40;&#40;startTime + 1000&#41; < currentTime&#41;
     &#123;
         //~1 second has passed
         printf&#40;"Recv called %d times in ~1 second\n", calls&#41;;
         calls=0;
         startTime=currentTime;
     &#125;
  &#125;
&#125;
Please report the # of times per second at which recv is called when using the MSG_DONTWAIT flag

2) MSG_DONTWAIT - are you sure that's not causing the problem
E.g., it peeks at the buffer without clearing it
Replace MSG_DONTWAIT with 0 to test how it works without this flag, but this will make the socket a blocking socket
Please see #4 to learn how to do nonblocking using the poll method

3) numhold - what type is it? Make it signed int, and then instead of:
if (numhold!=-1 && numhold!=0)

Do:
if (numhold > 0)

Sony error codes go into the negatives, and they're not just -1
So if the error code was -13123123, it would have been causing your if to printf() the previous data

4) If MSG_DONTWAIT is the problem, and you want non-blocking sockets, do this:

Code: Select all

signed int net_sock=SOCKET_UNINITIALIZED;

//Function returns -1 when error, 0 when no data received, and >0 when data received
signed int net_recv&#40;void *a_data, unsigned int a_size&#41;
&#123;
  struct timeval timeVal;
  signed int fdReadyTotal;
  fd_set fdReadFlag;

  //Initiate the block time
  timeVal.tv_sec=0;
  timeVal.tv_usec=1000; //Cannot be too low, or it'll DDoS the wlan from inside out
  //This is how long the select function should wait to see if data was received before calling recv

  //Reset the flag
  FD_ZERO&#40;&fdReadFlag&#41;;
  FD_SET&#40;net_sock, &fdReadFlag&#41;;

  //Generate the data regarding which file descriptor is free
  fdReadyTotal=select&#40;FD_SETSIZE, &fdReadFlag, NULL, NULL, &timeVal&#41;;

  if&#40;fdReadyTotal < 0&#41;
  &#123;
    printf&#40;"NetRecv&#58;Error - Select < 0\n"&#41;;
    return -1;
  &#125;
  
  //Is the socket ready?  
  if&#40;&#40;fdReadyTotal!=0&#41; && FD_ISSET&#40;net_sock, &fdReadFlag&#41;&#41;
  &#123;
    signed int recvRet=recv&#40;net_sock, a_data, a_size, 0&#41;;
  
    if&#40;recvRet <= 0&#41;
    &#123;
      printf&#40;"NetRecv&#58;Error - Recv <= 0\n"&#41;;
      return -1;
    &#125;

    return recvRet;
  &#125;

  return 0;
&#125;
PC tutorials might say that using FD_SETSIZE is idiotic, and to use net_sock+1 instead. This is not the case on the PSP, so stick to using FD_SETSIZE since each stream PSP handler contains bit flags, therefore net_sock+1 wouldn't work due to these bit flags. Well it'd work but the range needing to be checked would be > than the value of FD_SETSIZE. The solution is to do: (net_sock & SOME_VALUE) +1, but I at the moment don't remember what SOME_VALUE is - nor do I feel that it is of great importance
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

Thanks will try that! I remember having a problem with select in past tho. [frm Opera mini, cant use new line]I think abt 60 times /sec (sceDisplayWaitVBlankStart)

EDIT: As long data sent and recieved is current - 59-60.
Once data is stacked the call speed is between 30 - 52 and Laggy
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

I was very hopeful this would work... but.. Unfortunately stacking still happens (also nonblocking):

Stacking behaviour is slight different like this: Begins with 2 and continues with about 25...

Code: Select all

//Function returns -1 when error, 0 when no data received, and >0 when data received
signed int net_recv&#40;void *a_data, unsigned int a_size&#41;
&#123;
    signed int net_sock=sockfd; //sockfd already inited
  struct timeval timeVal;
  signed int fdReadyTotal;
  fd_set fdReadFlag;

  //Initiate the block time
  timeVal.tv_sec=0;
  timeVal.tv_usec=1000; //Cannot be too low, or it'll DDoS the wlan from inside out
  //This is how long the select function should wait to see if data was received before calling recv

  //Reset the flag
  FD_ZERO&#40;&fdReadFlag&#41;;
  FD_SET&#40;net_sock, &fdReadFlag&#41;;

  //Generate the data regarding which file descriptor is free
  fdReadyTotal=select&#40;FD_SETSIZE, &fdReadFlag, NULL, NULL, &timeVal&#41;;

  if&#40;fdReadyTotal < 0&#41;
  &#123;
    printf&#40;"NetRecv&#58;Error - Select < 0\n"&#41;;
    return -1;
  &#125;

  //Is the socket ready?
  if&#40;&#40;fdReadyTotal!=0&#41; && FD_ISSET&#40;net_sock, &fdReadFlag&#41;&#41;
  &#123;
    signed int recvRet=recv&#40;net_sock, a_data, a_size, 0&#41;;

    if&#40;recvRet <= 0&#41;
    &#123;
      printf&#40;"NetRecv&#58;Error - Recv <= 0\n"&#41;;
      return -1;
    &#125;

    return recvRet;
  &#125;

  return 0;
&#125;
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
Smong
Posts: 82
Joined: Tue Sep 04, 2007 4:44 am

Post by Smong »

What do you mean by stacking? Maybe the strings aren't always null terminated. You could try memset(&recvbuff, 0, 255); before a recv. Also it is interesting you are using &recvbuff and not recvbuff, how did you declare that variable?
(+[__]%)
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

Smong wrote:What do you mean by stacking? Maybe the strings aren't always null terminated. You could try memset(&recvbuff, 0, 255); before a recv. Also it is interesting you are using &recvbuff and not recvbuff, how did you declare that variable?
I tried clearing the buffer before using recv; that does the same thing as memset?

char recvbuff[255];

I donot think & and without would make any difference to strings since they are simply pointers in either way.

I will still try that.
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
Smong
Posts: 82
Joined: Tue Sep 04, 2007 4:44 am

Post by Smong »

KickinAezz wrote:I tried clearing the buffer before using recv; that does the same thing as memset?

char recvbuff[255];
Yes memset to 0 is the same as clearing the buffer.

&recvbuff is the not the same as recvbuff, unless you write it like &recvbuff[0]. Sounds like this was the problem.
(+[__]%)
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

Smong wrote:
KickinAezz wrote:I tried clearing the buffer before using recv; that does the same thing as memset?

char recvbuff[255];
Yes memset to 0 is the same as clearing the buffer.

&recvbuff is the not the same as recvbuff, unless you write it like &recvbuff[0]. Sounds like this was the problem.
IS IT? Really, didn't know that before!

WILL try asap.
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

NO, that was not the problem... Still exists...

Image
Image
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
SANiK
Posts: 29
Joined: Tue Jul 05, 2005 5:25 am

Post by SANiK »

1)
&recvbuff is the not the same as recvbuff, unless you write it like &recvbuff[0].
&recvbuff == &recvbuff[0] == recvbuff, when dealing with constant-arrays
When dealing with pointer arrays, that's when things change

2) Might the problem you're describing be Nagle-ing?

When one sends data, the network layer doesn't send it right away.
Instead, it groups the data and then sends them together
Smong
Posts: 82
Joined: Tue Sep 04, 2007 4:44 am

Post by Smong »

Thanks for the pointer tip.

I just noticed "TCP" in the topic name (heh), so your answer seems likely.

There's also the question of the string's terminating character, which I would expect after the trailing # of each hello. Maybe something to do with how they are being sent/echoed, for example using strlen() instead of strlen()+1.
(+[__]%)
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

SANiK wrote:1)
&recvbuff is the not the same as recvbuff, unless you write it like &recvbuff[0].
&recvbuff == &recvbuff[0] == recvbuff, when dealing with constant-arrays
When dealing with pointer arrays, that's when things change

2) Might the problem you're describing be Nagle-ing?

When one sends data, the network layer doesn't send it right away.
Instead, it groups the data and then sends them together
Regarding TCP nagling, I remember seeing it in RemoteJoy PC SRC; but didnt care much. If that solves the problem please let me know the implementation.
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
User avatar
Jim
Posts: 476
Joined: Sat Jul 02, 2005 10:06 pm
Location: Sydney
Contact:

Post by Jim »

This ain't gonna help you a jot and tittle, but

&recvbuff == &recvbuff[0] == recvbuff

Well, yes, on PSP they all have the same value, but what they don't need to share in any C compiler is their type. And, that means that they don't necessarliy have the same value...

char a[5];
&a has type 'pointer to array [5] of char'.
&a[0] has type 'pointer to first element of a' or 'pointer to char'
a has type 'pointer to first element of a' or 'pointer to char'

If you set warnings sufficiently high on your compiler you might find some more problems.

Jim
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

Jim wrote:This ain't gonna help you a jot and tittle, but

&recvbuff == &recvbuff[0] == recvbuff

Well, yes, on PSP they all have the same value, but what they don't need to share in any C compiler is their type. And, that means that they don't necessarliy have the same value...
Exactly. (applies to PSP)

----

I still need help solving this problem :|
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
jimparis
Posts: 1145
Joined: Fri Jun 10, 2005 4:21 am
Location: Boston

Post by jimparis »

It is quite possible that the MSG_DONTWAIT define is wrong; that is, flag==0x80 could a very different meaning on PSP than in the BSD headers used by newlib.
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

jimparis wrote:It is quite possible that the MSG_DONTWAIT define is wrong; that is, flag==0x80 could a very different meaning on PSP than in the BSD headers used by newlib.
No... It's actually works; Otherwise we would be totally 'stuck' unless server sends replies or anything back.

Problem is SOMETHING else! :(
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
Smong
Posts: 82
Joined: Tue Sep 04, 2007 4:44 am

Post by Smong »

While waiting for another solution you could tackle the stream problem by wrapping it in "packets". There are a few ways to do this:
- Always send the same length data.
- Add magic bytes, such as 0 or new line at the end of your data (you still didn't answer my question on whether you are sending/echoing the string nul-char correctly).
- Add header's containing the length of the "packet", you can also put other stuff in here like type.

Now once the receiving end knows the length it can chop up the incoming stream into the same pieces that were sent to it.
(+[__]%)
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

Smong wrote:While waiting for another solution you could tackle the stream problem by wrapping it in "packets". There are a few ways to do this:
- Always send the same length data.
- Add magic bytes, such as 0 or new line at the end of your data (you still didn't answer my question on whether you are sending/echoing the string nul-char correctly).
- Add header's containing the length of the "packet", you can also put other stuff in here like type.

Now once the receiving end knows the length it can chop up the incoming stream into the same pieces that were sent to it.
I ALREADY thought of that BUT

Once the recv buf gets "stacked"; it starts to slow down the whole process from

around 60fps to UNSTABLE around 10 - 52 fps...


Just think of what it would be like while playing a Racing game and suddenly our client (PSP) doesn't recieve any analog buttons or analog in the right time :)
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
SANiK
Posts: 29
Joined: Tue Jul 05, 2005 5:25 am

Post by SANiK »

Well - do note that you shouldn't be using the TCP protocol if you're writing a game.

Use UDP.
The PSP supports BSD sockets so any Linux UDP tutorial should do.

TCP sockets work by:
1) Send data
2) Wait for receiver to send back "acknowledge" signal
3) Send new packet

Thereby ensuring that all packets are sent in order

UDP is faster because it just sends and sends
The problem is that UDP packets:
1) Get lost
2) Might come out of order
3) Can be easily spoofed

Switching to UDP may not be your solution to this problem at the moment, BUT, it is a "mandatory" transition - or else your game is gonnah be very slow network wise
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

SANiK wrote:Well - do note that you shouldn't be using the TCP protocol if you're writing a game.

Use UDP.
The PSP supports BSD sockets so any Linux UDP tutorial should do.

TCP sockets work by:
1) Send data
2) Wait for receiver to send back "acknowledge" signal
3) Send new packet

Thereby ensuring that all packets are sent in order

UDP is faster because it just sends and sends
The problem is that UDP packets:
1) Get lost
2) Might come out of order
3) Can be easily spoofed

Switching to UDP may not be your solution to this problem at the moment, BUT, it is a "mandatory" transition - or else your game is gonnah be very slow network wise
No.. Not a game but using Xbox1 Controller Natively on PSP Games...

The TCP/IP stack on Xbox I work with isn't so good... Only TCP works stably. Any solutions to this problem? [Clear the PSP's recieve buffer?]
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

Hi KickinAezz,

I had the same kind of issue, the only way I found to solve this isn't satisfactory, but...

add just before your recv :

sceKernelDelayThread(40* 1000);

you may try a different delay.

It seems like the select tells you that the data are arrived, but when you try to recv them, there are not yet there (probably stack-ed somewhere else).

It's probably due to the thread model, which is cooperative (so you have to sleep sometime).

Hope this help.
--pspZorba--
NO to K1.5 !
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

pspZorba wrote:Hi KickinAezz,

I had the same kind of issue, the only way I found to solve this isn't satisfactory, but...

add just before your recv :

sceKernelDelayThread(40* 1000);

you may try a different delay.

It seems like the select tells you that the data are arrived, but when you try to recv them, there are not yet there (probably stack-ed somewhere else).

It's probably due to the thread model, which is cooperative (so you have to sleep sometime).

Hope this help.
Will try that.

I have to finalize my other project first and calmly bother with fixing this :D
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

The PSP apparently uses threads to handle the packets. While doing DOOM for the PSP, I found that sockets didn't work correctly unless you gave up time right before reading or sending a packet. However, the thread(s) appear to be a higher priority than the default as you don't have to give up much time - you just need to trigger the cooperative multitasking. I use sceKernelDelayThread(10); without a hitch.
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

Actually what is strange is that if I send a "small" ( < 100Meg) amount of datas I can set a small delay.

But I can't set less than 40 milli sec when I transmit lots of meg ( > 100 meg) otherwise at one moment or another there is a strange behavior.

By the way, J.F. what priorities are you using?
--pspZorba--
NO to K1.5 !
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

J.F. wrote:The PSP apparently uses threads to handle the packets. While doing DOOM for the PSP, I found that sockets didn't work correctly unless you gave up time right before reading or sending a packet. However, the thread(s) appear to be a higher priority than the default as you don't have to give up much time - you just need to trigger the cooperative multitasking. I use sceKernelDelayThread(10); without a hitch.
Do you use Non blocking or regular, With select or without? So Kdelay(10) before recv should most probably solve the problem? I'll post src once I find free time.
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
SANiK
Posts: 29
Joined: Tue Jul 05, 2005 5:25 am

Post by SANiK »

KickinAezz, please post your results when you do try the delay before the recv.


I've been having some socket issues as well but I decided to sleep on it.
My issue was that the recv() function would go from recving data instantly and on time, to receiving data 19 s after it was sent, and then recving data instantly again, etc.
(variable lag)

The delay might be a solution to my problem, but I can't test it at the moment *heh*

There's definitely something weird going on with sockets and I feel like we may be forgetting some little detail somewhere.

It'd be funny if this is all due to a random bug caused by implementing BSD sockets incorrectly

Speaking of BSD sockets, I wonder if "sceNetInetPoll" and "sceNetSetDropRate" may be of any use to us
Last edited by SANiK on Tue Aug 12, 2008 11:24 am, edited 1 time in total.
J.F.
Posts: 2906
Joined: Sun Feb 22, 2004 11:41 am

Post by J.F. »

KickinAezz wrote:
J.F. wrote:The PSP apparently uses threads to handle the packets. While doing DOOM for the PSP, I found that sockets didn't work correctly unless you gave up time right before reading or sending a packet. However, the thread(s) appear to be a higher priority than the default as you don't have to give up much time - you just need to trigger the cooperative multitasking. I use sceKernelDelayThread(10); without a hitch.
Do you use Non blocking or regular, With select or without? So Kdelay(10) before recv should most probably solve the problem? I'll post src once I find free time.
Non-blocking UDP packets w/o select. Most games use non-blocking UDP packets, and most old games don't use select while most new games do.

I used a number of different delays and found it didn't matter - it wasn't the amount of time I waited, just the fact that I waited that was important. That seems to me to indicate that the PSP had its own thread for sockets and was waiting for my main thread to wait so that it could run.
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

SANiK wrote: There's definitely something weird going on with sockets and I feel like we may be forgetting some little detail somewhere.

It'd be funny if this is all due to a random bug caused by implementing BSD sockets incorrectly
Well I don't think it is a bug, but it's more a problem coming from the cooperative thread model, since as soon as you add this delay you have no more issue.
--pspZorba--
NO to K1.5 !
KickinAezz
Posts: 328
Joined: Sun Jun 03, 2007 10:05 pm

Post by KickinAezz »

pspZorba wrote:
SANiK wrote: There's definitely something weird going on with sockets and I feel like we may be forgetting some little detail somewhere.

It'd be funny if this is all due to a random bug caused by implementing BSD sockets incorrectly
Well I don't think it is a bug, but it's more a problem coming from the cooperative thread model, since as soon as you add this delay you have no more issue.
NO; it's not resolved.

--

I donot what I changed but the lag is about 98% reduced; Seems PRETTY STABLE! BUT the STACKING EXISTS! I could parse the length of incoming data from server and read only that part but it would be better if things were perfect[/b]
"TCP_NODELAY
If set, disable the Nagle algorithm. This means that segments are always sent as soon as possible, even if there is only a small amount of data. When not set, data is buffered until there is a sufficient amount to send out, thereby avoiding the frequent sending of small packets, which results in poor utilization of the network. This option is overridden by TCP_CORK; however, setting this option forces an explicit flush of pending output, even if TCP_CORK is currently set. "
http://linux.die.net/man/7/tcp
Will try this out.

UPDATE:
socksetting=1;
setsockopt(sockfd,IPPROTO_TCP,TCP_NODELAY,&socksetting,sizeof(socksetting));

gives me

Code: Select all

main.c|427|error&#58; 'TCP_NODELAY' undeclared &#40;first use in this function&#41;|
Is this not applicable for PSP? Why?
Intrigued by PSP system Since December 2006.
Use it more for Development than for Gaming.
pspZorba
Posts: 156
Joined: Sat Sep 22, 2007 11:45 am
Location: NY

Post by pspZorba »

for TCP_NODELAY =>
#include <netinet/tcp.h>


About the delay what range of values did you try?
--pspZorba--
NO to K1.5 !
Post Reply