Hi all,
I have a server and a client program and they will comminicate with each other on an open socket.
The server code is something like this:
.data
ReceivingBuffer db 1000+1 dup(0)
Message1 db "Msg1", 0
Message2 db "Msg2", 0
.code
Invoke recv, OpenedSocketHandleForThisClient, Addr ReceivingBuffer, 1000, 0
Invoke send, OpenedSocketHandleForThisClient, Addr Message1, SizeOf Message1, 0
Invoke recv, OpenedSocketHandleForThisClient, Addr ReceivingBuffer, 1000, 0
Invoke send, OpenedSocketHandleForThisClient, Addr Message2, SizeOf Message2, 0
and the client code is something like this:
invoke send, S1, addr MyString, sizeof MyString, 0
invoke recv, S1, addr ReceivingBuffer, sizeof ReceivingBuffer, 0
invoke send, S1, addr MyString, sizeof MyString, 0
invoke recv, S1, addr ReceivingBuffer, sizeof ReceivingBuffer, 0
Print addr ReceivingBuffer
Now I expect that the client prints always "Message2" and it happens when I put 1 second delay between each loop that client sends and receives messages to and form the server. But when I run the client to send and receive messages countinously without any delay it will print sometimes (Message1) and sometimes (Message2). I don't know why this happens while I expect client and server to be synchronized by using this code! Can anybody help?
Besides when change the code as below:
Server:
Invoke recv, OpenedSocketHandleForThisClient, Addr ReceivingBuffer, 1000, 0
Invoke send, OpenedSocketHandleForThisClient, Addr Message1, SizeOf Message1, 0
Invoke send, OpenedSocketHandleForThisClient, Addr Message2, SizeOf Message2, 0
and client:
invoke send, S1, addr MyString, sizeof MyString, 0
invoke recv, S1, addr ReceivingBuffer, sizeof ReceivingBuffer, 0
invoke recv, S1, addr ReceivingBuffer, sizeof ReceivingBuffer, 0
in countinous sending, client program crashes. Can anybody help me to find a way to synchronize client and server tobe able to handle even incomming countinous messages from client?
Regards,
Danesh
What does OpenedSocketHandleForThisClient do?
Can you show us the code?
James: OpenedSocketHandleForThisClient would be the socket handle :P
Danesh: You'll have to post a full app - this could come from any number of things, but what you've posted looks fine.
Quote from: Danesh on August 22, 2006, 12:40:48 AMNow I expect that the client prints always "Message2" and it happens when I put 1 second delay between each loop that client sends and receives messages to and form the server. But when I run the client to send and receive messages countinously without any delay it will print sometimes (Message1) and sometimes (Message2). I don't know why this happens while I expect client and server to be synchronized by using this code! Can anybody help?
It's painfully obvious that you have a timing problem. But have not included, what controls the tcp flow in this code snippet. So there is no way of us helping your flow control.
Regards, P1 :8)
James: Yes, OpenedSocketHandleForThisClient is socket handle returned by "accept" function.
Tedd: here is the code attached.
P1: Here is my code attached. Yes P1, as you said I have timing problem. In fact I don't know when the other side is ready to receive to send data to it and in other word I have problem to synchronize both sides of network. I hope to get good tips from you to solve it.
Regards,
Danesh
[attachment deleted by admin]
It is a little strange, yes, I get the same result. Each function SHOULD block until it finishes, and therefore the messages will be received in order (not to mention it's a tcp socket, so the messages should stay in order!)
Testing the server with my own client (though it does use async), I get the following behaviour:
client->server: "1"
server->client: "Message 1"
client->server: "1"
server->client: "Message 2"
(loop)
So the server appears to work as expected.
Yet, when using your client: at the end of each loop - yes I would expect it to print "Message 2", being the last message to be received - it prints "Message 1" quite often :dazzled:
Reducing the client's loop to only one send-receive causes mainly "Message 1" to be printed, but sometimes "Message 2" -- strrrrrrange! (We would hope it was 1 then 2, then 1 then 2 then.....)
The only thing that comes to mind is that it's a consequence of running all on the same machine, so the sockets are 'local' and there must be some kind of (winsock internal) thread concurrency/shortcut issue - where each recv writes to the buffer, but the last one to finish is the one to be printed.
I think simply running the client(s) and server on separate machines will fix it anyway. (Since the sockets aren't on the same machine, plus network latency.)
For testing, you might just have to stick to putting the delay in manually.
If that doesn't fix it, it might be worth re-doing it with async sockets (WSAAsyncSelect) and then you know when the message has fully been received (this may be the reason my client works.)
Quote from: Tedd on August 22, 2006, 05:22:45 PMYet, when using your client: at the end of each loop - yes I would expect it to print "Message 2", being the last message to be received - it prints "Message 1" quite often :dazzled:
Reducing the client's loop to only one send-receive causes mainly "Message 1" to be printed, but sometimes "Message 2" -- strrrrrrange! (We would hope it was 1 then 2, then 1 then 2 then.....)
Buffers 101
He uses the same memory area without regard to reuse and/or clearing of messages. So he has overlapping calls without the proper timing flow control to ensure orderly output. IOW, sometimes you are printing "Message 1", just in time of the arival of "Message 2" without blocking until "Message 1" is printed.
Regards, P1 :8)
Yes, but we're expecting that send and recv should block and not return until their operations have finished (i.e. the data has been sent/received).
But obviously this isn't quite what's happening.
Quote from: Tedd on August 22, 2006, 05:22:45 PMIf that doesn't fix it, it might be worth re-doing it with async sockets (WSAAsyncSelect) and then you know when the message has fully been received (this may be the reason my client works.)
I would go that way myself as well. Maybe a simple ack/nak for flow control for check. A checksum for message corruption.
Regards, P1 :8)
Quote from: Tedd on August 22, 2006, 06:13:31 PMYes, but we're expecting that send and recv should block and not return until their operations have finished (i.e. the data has been sent/received).
Each stream is seperate. Expect blocking, only when you setup for it.
QuoteValue Meaning
SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams with an out-of-band data transmission mechanism. Uses TCP for the Internet address family.
Sockets of type SOCK_STREAM are full-duplex byte streams. A stream socket must be in a connected state before any data can be sent or received on it. A connection to another socket is created with a connect call. Once connected, data can be transferred using send and recv calls. When a session has been completed, a closesocket must be performed. Out-of-band data can also be transmitted as described in send and received as described in recv.
What were you expecting on a streaming socket on an improperly used buffer?
Regards, P1 :8)
tcp/ip already provides sequencing, ack, nack, checksum, flow control, windowing, ........ -- sockets of type SOCK_STREAM should provide this already.
How is the buffer improperely used? The send and recv functions are called sequentially, and they are (supposedly!) blocking - they should never attempt to access the buffer at the same time.
... Server
TextMessage DB "Message 1", 0
OKMsg db "Message 2", 0
... Server
GetMsgFromClient: ; getting query loop
Invoke recv, OpenedSocketHandleForThisClient, Addr ReceivingBuffer, 1000, 0
Invoke send, OpenedSocketHandleForThisClient, Addr TextMessage, SizeOf TextMessage, 0
Invoke recv, OpenedSocketHandleForThisClient, Addr ReceivingBuffer, 1000, 0
Invoke send, OpenedSocketHandleForThisClient, Addr OKMsg, SizeOf OKMsg, 0
... Client
invoke send, S1, addr QueryStr, sizeof QueryStr, 0 ; send the entered query to the server
invoke recv, S1, addr ReceivingBuffer, sizeof ReceivingBuffer, 0
invoke send, S1, addr QueryStr, sizeof QueryStr, 0 ; send the entered query to the server
invoke recv, S1, addr ReceivingBuffer, sizeof ReceivingBuffer, 0
To save some discussion here, please read what "SOCK_STREAM are full-duplex byte streams." means.
Quote from: Tedd on August 22, 2006, 06:26:08 PMHow is the buffer improperely used?
Why would he program two different messages to the same buffer back to back? Then expect the results to be different from the same buffer?
Regards, P1 :8)
full-duplex means the stream is 'capable' of sending and receiving at the same time.
(blocking) send completes once the data has been passed up to the network, ready to be sent - the buffer is free to use again
(blocking) recv completes when the data from the message has been received - the buffer now contains the received message
He is receiving two messages, a then b (yes, both into the same buffer), and printing the contents of the buffer - expecting only b to be printed, as this is the last to be received. This is not an insane expectation.
If we receive 'a', then when that call returns the buffer should contain message a. If we then receive 'b', then once that call returns the buffer should contain message b. Printing the buffer at this point should print message b. Since the calls are 'blocking,' each recv should not return until its message has been fully received, so there should be no overlap between the two calls.
I am sure what Tedd is saying is right. When "recv" is called it wait until a message come from other side. Improper using of buffer is quite irrelevant while it will be updated after each receive. I think, however, "recv" will block the execution until it is done, but "send" will send the data as soon as it is ready so the problem would be timing between a send a receive. In other words, sometimes a send will be done before proper receive is ready to receive and this happens when there are more than one receive and send in code. I need to know, how can I be sure that the other side is ready to receive, to send the data to it? I thought maybe a delay after each send would give the other side enough time to be ready to go to receive state, but it would depend on network traffic, network speed, etc.
Regards,
Danesh
Just let us know what works in the end. And what you figured out from that. That way we all can learn here.
Regards, P1 :8)
I don't think you should need to wait for the (application at the) other side to be ready to receive (or send, when receiving.)
Messages are buffered at either side by winsock, so the other side can be considered always ready - if it's not then the call will fail anyway.
When "send" returns successfully, all this means is that winsock has buffered your message has made a start on sending it. TCP provides 'connections' and so when you do a send, winsock knows it's being received on the other side - so the send call returns successfully.
When "recv" returns successfully, it means the message has been copied from winsock's buffer into yours. The actual message may have already been there (waiting in winsock's buffers) 20 seconds before you even call recv. Or, it could be that there was no message immediately and so your call waits until there is one, and you receive that.
So you shouldn't have any problems with synching between server and clients, as this is handled invisibly already.
I think the problem in this case is that the sockets are running on the same local machine. As a result, send could complete (on the 'other' end) even before it returns successfully. The problem itself could be a mixed consequence of this kind of shortcut - which should only result when the two are both running on the same machine.
So, what you need to do is test it across two separate machines, and see if you can reproduce this strange effect at all. If not, then this is probably what's causing it, and you can assume your program is 'correct.' (Assuming it's meant for multiple machines.)
P1: Sure I will share with everybody if I could come to any solution.
Tedd: I tested server and client programs on seprate machines and as I expected the problem still exists. In my tests, I ran the server on my notebook and client from my system. When I press enter (on client side) and hold it (it sends data countinously) it strats to get "Message 1" from server which seems to be good but after few seconds it send "Message 2" and then after few seconds "Message 1" and so on.
D.
Forget this headache :bdg
Learn how to use WSAAsyncSelect. The you can receive a message when the data has been received, which should avoid this problem.
Quote from: Tedd on August 24, 2006, 12:50:05 PMLearn how to use WSAAsyncSelect. The you can receive a message when the data has been received, which should avoid this problem.
Exactly !!! :U
I was checking up on SOCK_STREAM from a M$ source and it's not pretty. Reminds me of the old serial stuff that I had done.
Regards, P1 :8)
Sure. I will try WSAAsyncSelect.
Thanks P1 and Tedd. You showed me the way.