recv function for winsock socket - windows

I have a server application which is connected with telnet client(i.e. telnet localhost _port_num - here port number is same associated with the server application),
My application works correctly, but the thing is I used recv as follows:
#define BUFLEN 512
char buf[BUFLEN];
iResult = recv(sd, (char *)buf, BUFLEN, 0);
here recv call returns as soon as any character pressed over the connected telnet terminal, and most of the time iResult is 1 or some times 2, Even though I wouldn't press enter telnet client sends frame containing a single character to the server application.
How can I make sure that recv should return after BUFLEN read ?
In case of linux recv works as expected, get blocks until enter.
Any help or pointers are greatly appreciated.

Q: How can I make sure that ... BUFLEN read ?
A: You read in a loop until you get all the characters you expect. Or until you get a timeout, or an error.

You need to call recv function again and again until your desired amount of data is received. Please note that when you use TCP Sockets, you cannot make sure if you receive all data in single receive call. If you send data using single TCP Send() call, then it is fairly possible that you receive it in multiple receives as TCP sockets are Stream Sockets.
The recv() function returns the number of bytes received, so you can keep calling the function until you get all they bytes.

Related

Trying to send a FIX api message to ctrader server using Ruby but receiving no response

Trying to see if I can get a response from ctrader server.
Getting no response and seems to hang at "s.recv(1024)". So not sure what could be going wrong here. I have limited experience with sockets and network coding.
I have checked my login credentials and all seems ok.
Note: I am aware of many FIX engines that are available for this purpose but wanted to
try this on my own.
ctrader FIX guides
require 'socket'
hostname = "h51.p.ctrader.com"
port = 5201
#constructing a fix message to see what ctrader server returns
#8=FIX.4.4|9=123|35=A|49=demo.ctrader.*******|56=cServer|57=QUOTE|50=QUOTE|34=1|52=20220127-16:49:31|98=0|108=30|553=********|554=*******|10=155|
fix_message = "8=FIX.4.4|9=#{bodylengthsum}|" + bodylength + "10=#{checksumcalc}|"
s = TCPSocket.new(hostname, port)
s.send(fix_message.force_encoding("ASCII"),0)
print fix_message
puts s.recv(1024)
s.close
Sockets are by default blocking on read. When you call recv that call will block if no data is available.
The fact that your recv call is not returning anything, would be an indication that the server did not send you any reply at all; the call is blocking waiting for incoming data.
If you would use read instead, then the call will block until all the requested data has been received.
So calling recv(1024) will block until 1 or more bytes are available.
Calling read(1024) will block until all 1024 bytes have been received.
Note that you cannot rely on a single recv call to return a full message, even if the sender sent you everything you need. Multiple recv calls may be required to construct the full message.
Also note that the FIX protocol gives the msg length at the start of each message. So after you get enough data to see the msg length, you could call read to ensure you get the rest.
If you do not want your recv or read calls to block when no data (or incomplete data) is available, then you need to use non-blocking IO instead for your reads. This is complex topic, which you need to research, but often used when you don't want to block and need to read arbitary length messages. You can look here for some tips.
Another option would be to use something like EventMachine instead, which makes it easier to deal with sockets in situations like this, without having to worry about blocking in your code.

TCP data before session closing

Is there anyway that will allow to get all data sent via tcp before the session gets closed?
What I am getting is I have to close the session from server only after that data is received, and moreover I have to manually pass EOL or carriage-return or "\n" or "\r".
Any help and suggestions is appreciated.
You could try setting the SO_LINGER socket option:
GCDAsyncSocket asyncSocket = ...;
struct linger linger;
linger.l_onoff = 1;
linger.l_linger = 30;
int rv = setsockopt([asyncSocket socketFD], SOL_SOCKET, SO_LINGER, &linger, sizeof(linger));
if (rv < 0)
{
// handle error
}
Is there anyway that will allow to get all data sent via tcp before the session gets closed?
You keep reading data from the socket till EOF is received.
What I am getting is I have to close the session from server only after that data is received
Technically, one can close your write side of the TCP connection, using shutdown(socket, SHUT_WR) indicating that this peer is not going to send any more data. But it will still need to read all the data till EOF is seen and then close(socket).
and moreover I have to manually pass EOL or carriage-return or "\n" or "\r"
This has little to do with sockets or TCP, rather with a higher application protocol, such as HTTP. There are libraries available for this popular protocol that simplify this task.

Padded data in recv() api

I am working on TCP client server application using c++.third party lib are now allowed in this project.
Here exchange between client server takes using well define protocol format.once the client receives the packet it will send it for parsing.I have protocol manager which will take care of the parsing activity.
I have following doubt
When the data arrives at client from the network, the OS buffers it until application calls recv() function.
So two message msg1 and msg2 arrives at the buffer a call to recv will return msg1+msg2. Now this may result in failure of the parsing activity.
My queries
1. whether above mentioned assumption is correct or not ?
2. If above mentioned assuption is correct then how can resolve this issue.
Revathy,
What you need to do here is make a fixed length packet or at-least fixed length header followed by variable length data.
The header should contain size of the packet. So In the recv function you always read the header bytes and decode the size of the packet and read the rest of the packet using another recv call.
This way even when your TCP layer buffers any number of packets you will be able to read it correctly
unsigned char* pBuffer = NULL;
pBuffer = new unsigned char[MESSAGE_HEADER_LENGTH];
// reading header from socket
int nRet = recv(sock,(char*)pBuffer,MESSAGE_HEADER_LENGTH,0);
int nDataLen = //Read the packet length from pBuffer
// reading body from socket
unsigned char* pPacket = NULL;
pPacket= new unsigned char[nDataLen ];
nRet = recv(sock,(char*)pPacket ,nDataLen ,0 );
In TCP, you cannot see packet boundaries, so if both packets arrive before you get to call recv(), you will get both packets' contents in a single go.
In UDP, packet boundaries are preserved, so each call to recv() gives back one packet.

Block TCP-send till ACK returned

I am programming a client application sending TCP/IP packets to a server. Because of timeout issues I want to start a timer as soon as the ACK-Package is returned (so there can be no timeout while the package has not reached the server). I want to use the winapi.
Setting the Socket to blocking mode doesn't help, because the send command returns as soon as the data is written into the buffer (if I am not mistaken). Is there a way to block send till the ACK was returned, or is there any other way to do this without writing my own TCP-implementation?
Regards
It sounds like you want to do the minimum implementation to achieve your goal. In this case you should set your socket to blocking, and following the send which blocks until all data is sent, you call recv which in turn will block until the ACK packet is received or the server end closes or aborts the connection.
If you wanted to go further with your implementation you'd have to structure your client application in such a way that supports asynchronous communication. There are a few techniques with varying degrees of complexity; polling using select() simple, event model using WSASelectEvent/WSAWaitForMultipleEvents challenging, and the IOCompletionPort model which is very complicated.
peudocode... Will wait until ack is recevied, after which time you can call whatever functionallity you want -i chose some made up function send_data.. which would then send information over the socket after receiving the ack.
data = ''
while True
readable, writable, errors = select([socket])
if socket in readble
data += recv(socket)
if is_ack(data)
timer.start() #not sure why you want this
break
send_data(socket)

socket behaviour when in blocking mode

I'm interested in the behavior of send function when using a blocking socket.
The manual specifies nothing about this case explicitly.
From my tests (and documentation) it results that when using send on a blocking socket I have 2 cases:
all the data is sent
an error is returned and nothing is sent
In lines of code (in C for example) this translate like this:
// everything is allocated and initilized
int socket_fd;
char *buffer;
size_t buffer_len;
ssize_t nret;
nret = send(socket_fd, buffer, buffer_len, 0);
if(nret < 0)
{
// error - nothing was sent (at least we cannot assume anything)
}
else
{
// in case of blocking socket everything is sent (buffer_len == nret)
}
Am I right?
I'm interested about this behavior on all platforms (Windows, Linux, *nix).
From the man page. (http://linux.die.net/man/2/send)
"On success, these calls return the number of characters sent. On error, -1 is returned, and errno is set appropriately. "
You have three conditions.
-1 is a local error in the socket or it's binding.
Some number < the length: not all the bytes were sent. This is usually the case when the socket is marked non-blocking and the requested operation would block; the errno value is EAGAIN.
You probably won't see this because you're doing blocking I/O.
However, the other end of the socket could close the connection prematurely, which may lead to this. The errno value would probably be EPIPE.
Some number == the length: all the bytes were sent.
My understanding is that a blocking send need not be atomic, see for example the Solaris send man page:
For socket types such as SOCK_DGRAM and SOCK_RAW that require atomic messages,
the error EMSGSIZE is returned and the message is not transmitted when it is
too long to pass atomically through the underlying protocol. The same
restrictions do not apply to SOCK_STREAM sockets.
And also look at the EINTR error code there:
The operation was interrupted by delivery of a signal before any data could
be buffered to be sent.
Which indicates that send can be interrupted after some data has been buffered to be sent - but in that case send would return the number of bytes that have already been buffered to be sent (instead of an EINTR error code).
In practice I would only expect to see this behaviour for large messages (that can not be handled atomically by the operating system) on SOCK_STREAM sockets.

Resources