Where communities thrive


  • Join over 1.5M+ people
  • Join over 100K+ communities
  • Free without limits
  • Create your own community
People
Repo info
Activity
  • Nov 16 18:35
    rlebeau commented #201
  • Nov 14 18:08
    wqmeng commented #201
  • Nov 14 18:04
    arvanus commented #201
  • Nov 14 17:43
    wqmeng commented #201
  • Nov 14 17:37
    arvanus commented #201
  • Nov 14 17:31
    wqmeng commented #201
  • Nov 14 12:00
    arvanus commented #201
  • Nov 14 09:07
    wqmeng commented #201
  • Nov 14 09:05
    wqmeng commented #201
  • Oct 30 16:15
    rlebeau edited #260
  • Oct 16 04:22
    rlebeau labeled #269
  • Oct 16 04:22
    rlebeau opened #269
  • Oct 08 19:00

    Fulgan on Restructure

    Bug fix for a typo in TIdIMAP4.… (compare)

  • Oct 08 19:00

    Fulgan on master

    Bug fix for a typo in TIdIMAP4.… (compare)

  • Oct 02 21:00

    Fulgan on Restructure

    Updating TIdIMAP4's InternalSea… (compare)

  • Oct 02 21:00

    Fulgan on master

    Updating TIdIMAP4's InternalSea… (compare)

  • Sep 20 21:50

    Fulgan on master

    Embarcadero patch for race cond… (compare)

  • Sep 20 21:50

    Fulgan on Restructure

    Embarcadero patch for race cond… (compare)

  • Sep 10 18:50
    rlebeau closed #268
  • Sep 10 18:50
    rlebeau commented #268
Remy Lebeau
@rlebeau
However, that is actually not necessary, because your server code is wrong to begin with. Your client is sending a data packet that has a fixed header on it that includes the data size in it. You server code is completely ignoring that header. You need to have the server read the header, then read the specified number of bytes, then you can pass the completed packet to OnReceive. Then there is no problem.
SetLength(arrBuf, 8); argContext.Connection.IOHandler.ReadBytes(arrBuf, 8); argContext.Connection.IOHandler.ReadBytes(arrBuf, PInteger(@arrBuf[4])^, True); OnReceive(@arrBuf[0], Length(arrBuf));
Remy Lebeau
@rlebeau
Note that you are sending integers in host byte order, which means you are subject to endian differences between the client and server. You really should be using network byte order instead. If you are not going to use the IOHandler's Read/Write methods for integer values, at least use Indy's GStack.HostToNetwork() function before sending the data, and the GStack.NetworkToHost() function after receiving the data, to make sure the integers are in a consistent endian on the wire.
PUInt32(@ sendBuf [0])^ := GStack.HostToNetwork(UInt32(CMDCOMMU_HEADER)); PUInt32(@ sendBuf [4])^ := GStack.HostToNetwork(UInt32(bufsize)); ... PUInt32(@ arrBuf [0])^ := GStack.NetworkToHost(PUInt32(@ arrBuf [0])^); PUInt32(@ arrBuf [4])^ := GStack.NetworkToHost(PUInt32(@ arrBuf [4])^);
Remy Lebeau
@rlebeau
Otherwise, use the IOHandler's reading/writing functions: with cmdClient.fIdClient.IOHandler do begin Write(Int32(CMDCOMMU_HEADER)); Write(Int32(bufsize)); Write(buf); end; ... with argContext.Connection.IOHandler do begin PktType := ReadInt32; PktSize := ReadInt32; ReadBytes(arrBuf, PktSize); end;
fan_tangshan
@sainimu78
@rlebeau Telling me so much, thanks, I will try InputBufferIsEmpty.
Are there simple ways to handle non-fixed size large buffer receiving and to receive buffer with no sticky packs?
Do uses GStack.HostToNetwork to prevent some network device reading error?
Remy Lebeau
@rlebeau
What is the point of putting a fixed header on the packets if your server is not going to use the header for reading the packet? You really shouldn't be doing arbitrary reading in this situation. You know the exact data size up front, so just ask Indy to read that many bytes. Problem solved.
fan_tangshan
@sainimu78
packet splicing
Remy Lebeau
@rlebeau
What are you talking about?
fan_tangshan
@sainimu78
I don't know what it calls, it's just two or more packets received at one time when using TIdTCPServer
Remy Lebeau
@rlebeau
TCP is a byte stream, it doesn't matter if the data is tranmitted on the wire in 1 packet or 100 packets. TCP guarantees reliable delivery. The bytes will be accurate on the receiving end, no matter how many packets it has to read. But, if you want to reduce the number of TCP packets transmitted, you can use Indy's write buffering when sending a packet, eg: with cmdClient.fIdClient.IOHandler do begin WriteBufferOpen; try Write(...); Write(...); Write(...); WriteBufferClose; except WriteBufferCancel; raise; end end;
fan_tangshan
@sainimu78
Then my need is call packet based TCP?
Freq, client sends two times, server gets just one time.
Some real time requirement
Remy Lebeau
@rlebeau
TIdTCPClient and TIdTCPServer use TCP, hence their names. Do you understand how TCP actually works? Do you understand that there is no 1-to-1 relationship between sends and reads in TCP (unlike in UDP)? You could sent 100 bytes 1 time, but read 1 byte 100 times. TCP guarantees the bytes are delivered, and in the right order, but how you send the bytes does not affect how you read the bytes and vice versa.
In any case, regarding the 2-sends 1-read issue, it likely has to do with how ReadBytes(-1) interacts with the InputBuffer. After the OnExecute event exits, the server calls IOHandler.Connected before firing OnExecute again. Connected performs a read, so it is possible that bytes are getting read into the InputBuffer and a subsequent ReadBytes(-1) is not checking for them before waiting for more bytes to arrive on the socket. If you were reading the packet header, like you should be, you wouldn't have that issue.
fan_tangshan
@sainimu78
I see, I know how to do
fan_tangshan
@sainimu78
I start a thread.
fan_tangshan
@sainimu78
A connection thread in client
In thread.Execute
while(Terminated = False)do
if(client.Connected = False)then
client.Disconnect;
Sleep(100);
The client will get Run Error 204 while server transferring data in client transferring way.
The transferring way is
blob
blob
It is just like you told me before @rlebeau
fan_tangshan
@sainimu78
Oh, sorry, my fault, I never thought it is a misusing of converting PByte to TIdBytes because I specified the size to IoHandler.Write.
fan_tangshan
@sainimu78
Or the other way of asking that how to detect disconnection on TIdTCPClient ?
fan_tangshan
@sainimu78
Here is my server.OnExecute doing
blob
Toggles between ReadBytes(8) and ReadBytes(argConn.bufSize)
blob
fan_tangshan
@sainimu78
TIdTCPClient.Connected is not thread safe, I think.
A mutex needs to be added on TIdTCPClient.IoHandler.ReadBytes call in the receive thread and on TIdTCPClient.Connected in the connection thread.
I found that the client receive thread can be aborted by the exception of the calling IoHandler.ReadBytes, then the problem solved.
Remy Lebeau
@rlebeau
You really shouldn't be calling Connected at all. Let the IOHandler throw an exception during read/write operations if the socket has been disconnected.
If you don't want the thread to terminate, catch the exception
fan_tangshan
@sainimu78

What Is wrong in this implementation?

In the client, I start a receive thread:
--the receive thread in the client:
----TIdTCPClient.IoHandler.ReadBytes
in the server:
--OnExcute:
----AContext.Connection.IoHandler.ReadBytes
If I first start the test transferring of the client sending data of < 80000 bytes to the server 10000 times and then do the same test reverse of the server sending to the client, there is nothing abnormal.
But if I first start the test of the server sending to the client and then the transferring speed becomes very low when do the test of the client sending to the server.

Remy Lebeau
@rlebeau
I can't answer that without seeing your actual code
fan_tangshan
@sainimu78
The test is one app sends data in size of < 7kb 100000 times to the other one.
If I never click the Server Send button to start the test of the server sending to the client and just do test the client to the server, it takes about 40~50 seconds in every test.
But if I click the Server Send once, the test of the client to the server sending will take apparently longer time than before.
QQ图片20160811020720.png
Here is the common read write procedure
blob
fan_tangshan
@sainimu78
The server
blob
The client
blob
fan_tangshan
@sainimu78
So simple test it is, I believe you'd tested it at the very beginning
Remy Lebeau
@rlebeau
well, it kind of makes sense, if you take into account that the client code is single-threaded but the server code is multi-threaded, so you are likely getting task switches during the server-to-client sending that are slowing it down compared to the client-to-server sending. Remember, TIdTCPServer runs each client in its own worker thread. Even if there is only 1 client connected, there are still other threads running (the main UI thread, the server's listening thread, etc) that the OS has to service in a timely manner.
fan_tangshan
@sainimu78
No, I don't think so. It's normal when I test the client-server sending with fixed bytes.
There may have some bad implementations doing with that.
blob
fan_tangshan
@sainimu78
After doing the server-client sending test, every client-server sending makes CPU usage rate high. If you are listening music you can hear lag sound.
So I guess the non-fixed bytes sending causes some threads work so hard in TIdTCPServer if the TIdContext.Connection.IoHandler cached something when Write().
davidpn
@davidpn
I thought I cancelled Lex's post that you replied to in the .winsock group.. it was an out-and-out lie (a repeat of the same one, I know)
fan_tangshan
@sainimu78
Is it not a problem? @rlebeau