Socket programming problem: Is the new socket fd used only once? - c

I want to write basic chat program. I don't release that, I just want to learn socket programming. The chat program will be between client and server.
server code:
//bla bla code
new_socket = accept(server_fd, (struct sockaddr*)&address,(socklen_t*)&addrlen);
char server_msg[128];
char client_msg[128];
int running = 1;
while(running){
fgets(server_msg, 64, stdin);
send(new_socket, server_msg, strlen(server_msg), 0);
recv(new_socket, client_msg, 128, 0);
}
client code:
char server_msg[128];
char client_msg[128];
int running = 1;
while(running){
fgets(client_msg, 64, stdin);
send(server_socket, client_msg, strlen(client_msg), 0);
recv(server_socket, server_msg, 128, 0);
}
Questions:
Is the new socket fd used only once? That means; Will I do create a new socket for each sending and receiving. Or can I use this forever?
If first question answer is "FOREVER", Will I do something to new socket fd? I don't know maybe clear.
The above code is not working as expected. As I expected. Actually, The code is working very well :D. How do I perform interrupt operations such as getting input, sending messages, receiving messages?
My English is not good, I'm sorry.

Is the new socket fd used only once? That means; Will I do create a new socket for each sending and receiving. Or can I use this forever?
you open a TCP socket connection, so, once in the connected state (the ESTABLISHED state) it remains there until one side closes it (and the other side will notice it by reading 0 bytes as result, this explanation is oversimplified to make it simpler to your case, normally you should detect the end of file in the socket, so you can close it, and accept(2) another connection)
If first question answer is "FOREVER", Will I do something to new socket fd? I don't know maybe clear.
Your program is not a chat program, as the server uses the SAME socket to write what it has read, so it will return the message sent to the same client that issued it (acting more as an echo server, than a chat)
The above code is not working as expected. As I expected. Actually, The code is working very well :D. How do I perform interrupt operations such as getting input, sending messages, receiving messages?
Normally, a chat server should wait for a message to arrive at several sockets (by means of the select(2) system call) and will determine which socket needs attention. As a result, the server will read(2) from that socket (probably in a non blocking way, to avoid being blocked on a read to a socket, that will not be interrupted if data enters on another socket) The chat server should write what it has read over all the other sockets it has connections from, so every other user of your chat system receives a copy of the message (sending back the message to the sender is optional, but not very elegant, the issuer of the message should do local echo of it, although, to ensure the user sees his messages interspersed between the ones from other users)
I recommend you to read the book "Unix Network Programming" from Richard Stevens. It describes perfectly how to use the sockets API and IMHO it is the best reference you can get to learn how to use the socket interface.
One final note:
Don't use plain numbers hardwired in your code, as it is error prone (you declare a buffer string to be 128 bytes, but then read only 64, making 64 unused bytes in the array, you can use sizeof buffer as to make the compiler to use the amount declared in the variable, or you can #define BUFFSIZE 128 and then declare char buffer[BUFFSIZE]; and later do a fgets(buffer, BUFFSIZE, socket_FILE_descriptor); if you use a constant to size a buffer, use a constant name to name it :) and use it everywhere, in case you decide to give it a different value, all the occurences of it will change, instead of having to reviste all places in your code where you have used the number 64.

Related

Sending multiple strings over tcp soket in C loses data [duplicate]

This question already has answers here:
Is there complete isolation between two sendalls in the same TCP connection?
(1 answer)
Can't receive multiple messages on server using TCP socket (Python)
(1 answer)
Python TCP Server receives single TCP packet split into multiple packets
(2 answers)
Closed 8 months ago.
I'm working on a C project that implements a TCP client-server. The sockets and the send() functions i'm using are the one defined in the libraries sys/socket.h and winsock2.h.
My problem is that when i try to send multiple strings one after the other, some messages aren't transmitted correctly, with some data (sometimes all the message) that goes missing. The following code, for example, works without a problem when i'm running server and client on the same machine, but if I try to run it with a remote server, then the third message isn't properly received.
Client Side
char message[1024];
memset(message, 0, 1024);
fill_message(message, msg1); //A function that prints something in the message string.
//It may fill less than 1024 characters.
send(clientSocket, message, 1024,0);
fill_message(message, msg2);
send(clientSocket, message, 1024,0);
fill_message(message, msg3);
send(clientSocket, message, 1024,0);
Server Side
char message[1024];
memset(message, 0, 1024);
recv(clientSocket, message, 1024,0);
print_and_do_stuff(message);
recv(clientSocket, message, 1024,0);
print_and_do_stuff(message);
recv(clientSocket, message, 1024,0);
print_and_do_stuff(message);
Note: the string message may not be exactly of length 1024.
My solution has been to make the client wait for 1 second by calling sleep(1) after each message is sent. Is this the proper way to address the issue? Or am i missing something about how send() and recv() work?
More in general: what is the "proper" way to program with sockets? Should I maybe be sending the message byte-by-byte and specifying the length as the first thing? If someone could point me toward a good tutorial/guide on what the best practices are when working with sockets, I'd be happy to read it.
Socket functions may or may not read/send the entire data in one call, which means that you have to verify the correct reception server side, and maybe create a custom protocol on top of TCP to keep track of the size you sent and received.
TCP, contrary to UDP, guarantees the integrity of data, meaning that you won't lose anything when sending, but you may need to use multiple function calls to ensure all of the data has been sent and red.
As for good tutorial and guides, as someone already said in comments, you can find loads of examples and guides about it.

tcp send and recv: always in loops?

What are the best practices when sending (or writing) and recving (or reading) to/from a TCP socket ?
Assume usual blocking I/O on sockets. From what I understand :
writing (sending) should be fine without a loop, because it will block if the write buffer of the socket is full, so something like
if ((nbytes_w = write(sock, buf, nb)) < nb)
/* something bad happened : error or interrupted by signal */
should always be correct ?
on the other hand, there is no guaranty that one will read a full message, so one should read with
while ((nbytes_r = read(sock, buf, MAX)) > 0) {
/* do something with these bytes */
/* break if encounter specific application protocol end of message flag
or total number of bytes was known from previous message
and/or application protocol header */
}
Am I correct ? Or is there some "small message size" or other conditions allowing to read safely outside a loop ?
I am confused because I have seen examples of "naked reads", for instance in Tanenbaum-Wetherall:
read(sa, buf, BUF_SIZE); /* read file name in socket */
Yes you must loop on the receive
Once a week I answer a question where someones TCP app stops working for this very reason. The real killer is that they developped the client and server on the same machine, so they get loopback connection. Almost all the time a loopback will receive the send messages in the same blocks as they were sent. This makes it look like the code is correct.
The really big challenge is that this means you need to know before the loop how big the message is that you are going to receive. Possibilities
send a fixed length length (ie you know its , say, 4 bytes) first.
have a recognizable end sequence (like the double crlf at the end of an HTTP request.
Have a fixed size message
I would always have a 'pull the next n bytes' function.
Writing should loop too, but that easy, its just a matter of looping.

ZeroMQ - Emulating standard socket for multiple clients to one server

I am hoping to utilise ZeroMQ in order to handle queuing of a large number of requests coming in at the same time to an attestation server.
I am in an HPC environment and so have a large number of compute nodes all running the same launcher program that attests with a server. This server code runs on a front-end node and after successfully attesting the client, will then release a key in order for the client to decrypt job data.
Currently standard sockets are used. When a client initially sends something to the server a new socket is spawned using accept() from sys/socket.h. This allows the client and server to send multiple messages between each other in the attestation process (checksums etc) before finally returning the key if successful.
The issue with ZeroMQ is that the attach command is not necessary and so a secondary socket for that specific attestation is not created. All the messages are dealt with from all the clients in whatever order they come in, leading to the multi-part attestation process not working. I have spent ages going through the guide and googling to try and find a similar solution but have not had any luck so far.
Is there a way I can utilise ZeroMQ to give the same behaviour in this application as a standard socket?
Q : Is there a way I can utilise ZeroMQ to give the same behaviour in this application as a standard socket?
ZeroMQ is a very smart and rather behaviour-oriented signaling / messaging-platform for distributed-systems, not a socket.
Given your intentions are to be worth for HPC-ecosystem, a solution postulated / directed to use some tool and a must to bend it as much as possible, so as it will become close to resemble a behaviour that is native, but for other tool, does not seem to be a typical HPC-grade approach.
HPC-code is typically very well-crafted so as to become computing-costs-efficient ( and bless the Boss, CFO & gov/mil-funding for all those, who are today permitted not to design the HPC-code for the ultimate performance and hardware-resources' use efficiency :o) ) - here, if one pays expenses on ZeroMQ instantiations, there seems no benefit to come from these non-zero costs of instantiations and getting "just"-a-socket-alike behaviour, at cost, has negative performance yield, without any adjustments in some future benefits from smart, cluster-wide ZeroMQ services ( be it an N+1 or N+M redundancy, low-latency smart inter-node cluster signaling, cryptography, cheap security-motivated white-listing, or anything that may represent any additional HPC-grade Project's benefit, that may justify the costs of the initial ZeroMQ instantiation ).
Defined archetype of ZMQ_STREAM may provide some tools, yet, ref. above
A socket of type ZMQ_STREAM is used to send and receive TCP data from a non-ØMQ peer, when using the tcp:// transport. A ZMQ_STREAM socket can act as client and/or server, sending and/or receiving TCP data asynchronously.
When receiving TCP data, a ZMQ_STREAM socket shall prepend a message part containing the identity of the originating peer to the message before passing it to the application. Messages received are fair-queued from among all connected peers.
When sending TCP data, a ZMQ_STREAM socket shall remove the first part of the message and use it to determine the identity of the peer the message shall be routed to, and unroutable messages shall cause an EHOSTUNREACH or EAGAIN error.
To open a connection to a server, use the zmq_connect call, and then fetch the socket identity using the ZMQ_IDENTITY zmq_getsockopt call.
To close a specific connection, send the identity frame followed by a zero-length message (see EXAMPLE section).
When a connection is made, a zero-length message will be received by the application. Similarly, when the peer disconnects (or the connection is lost), a zero-length message will be received by the application.
You must send one identity frame followed by one data frame. The ZMQ_SNDMORE flag is required for identity frames but is ignored on data frames.
ZMQ_STREAM Example:
void *ctx = zmq_ctx_new (); assert (ctx && "Context Instantiation Failed..." );
void *socket = zmq_socket (ctx, ZMQ_STREAM); assert (socket && "socket Instantiation Failed..." );
int rc = zmq_bind (socket, "tcp://*:8080"); assert (rc == 0 && "socket.bind() Failed..." );
uint8_t id [256]; /* Data structure to hold the ZMQ_STREAM ID */
size_t id_size = 256;
uint8_t raw [256]; /* Data structure to hold the ZMQ_STREAM received data */
size_t raw_size = 256;
while (1) {
id_size = zmq_recv (socket, id, 256, 0); assert (id_size > 0 && "Get HTTP request; ID frame and then request; Failed..." )
do {
raw_size = zmq_recv (socket, raw, 256, 0); assert (raw_size >= 0 && "socket.recv() Failed..." );
} while (raw_size == 256);
char http_response [] = /* Prepares the response */
"HTTP/1.0 200 OK\r\n"
"Content-Type: text/plain\r\n"
"\r\n"
"Hello, World!";
zmq_send (socket, id, id_size, ZMQ_SNDMORE); /* Sends the ID frame followed by the response */
zmq_send (socket, http_response, strlen (http_response), 0);
zmq_send (socket, id, id_size, ZMQ_SNDMORE); /* Closes the connection by sending the ID frame followed by a zero response */
zmq_send (socket, 0, 0, 0);
}
zmq_close (socket);
zmq_ctx_destroy (ctx);
ZeroMQ zmq_getsockopt() can deliver a POSIX/SOCKET descriptor, for low-level tricks
The ZMQ_FD option shall retrieve the file descriptor associated with the specified socket. The returned file descriptor can be used to integrate the socket into an existing event loop; the ØMQ library shall signal any pending events on the socket in an edge-triggered fashion by making the file descriptor become ready for reading.
The ability to read from the returned file descriptor does not necessarily indicate that messages are available to be read from, or can be written to, the underlying socket; applications must retrieve the actual event state with a subsequent retrieval of the ZMQ_EVENTS option.
The returned file descriptor is also used internally by the zmq_send and zmq_recv functions. As the descriptor is edge triggered, applications must update the state of ZMQ_EVENTS after each invocation of zmq_send or zmq_recv.
To be more explicit: after calling zmq_send the socket may become readable (and vice versa) without triggering a read event on the file descriptor.
The returned file descriptor is intended for use with a poll or similar system call only. Applications must never attempt to read or write data to it directly, neither should they try to close it.
Option value type: int on POSIX systems, SOCKET on Windows
For more details on ZeroMQ tricks one may enjoy to read solutions, performance benchmarks, latency-shaving details and other problem-solving tricks that have already been discussed here.

TCP Sockets in C with bad network

I am doing some test with TCP client application in a Raspberry Pi (server in the PC), with PPP (Point to Point Protocol) using a LTE Modem. I have used C program with sockets, checking system call's response. I wanted to test how socket works in a bad coverage area so I did some test removing the antenna.
I have followed the next steps:
Connect to server --> OK
Start sending data (write system call) --> OK (I also check in the server)
I removed the LTE modem's antenna (There is no network, it can't do ping)
Continue sending data (write system call) --> OK (server does not receive anything!!!)
It finished sending data and closed socket --> OK (connection is still opened and there is no data since the antenna was removed)
Program was finished
I put the antenna again
Some time later, the data has been uploaded and the connection closed. But I did another test following this steps but with more data, and it did not upload this data...
I do not know if there any way to ensure that the data written to TCP server is received by the server (I thought that TCP layer ensured this..). I could do it manually using an ACK but I guess that it has to be a better way to do.
Sending part code:
while(i<100)
{
sprintf(buf, "Message %d\n", i);
Return = write(Sock_Fd, buf, strlen(buf));
if(Return!=strlen(buf))
{
printf("Error sending data to TCP server. \n");
printf("Error str: %s \n", strerror(errno));
}
else
{
printf("write successful %d\n", i);
i++;
}
sleep(2);
}
Many thanks for your help.
The write()-syscall returns true, since the kernel buffers the data and puts it in the out-queue of the socket. It is removed from this queue when the data was sent and acked from the peer. When the OutQueue is full, the write-syscall will block.
To determine, if data has not been acked by the peer, you have to look at the size of the outqueue. With linux, you can use an ioctl() for this:
ioctl(fd, SIOCOUTQ, &outqlen);
However, it would be more clean and portable to use an inband method for determining if the data has been received.
TCP/IP is rather primitive technology. Internet may sound newish, but this is really antique stuff. TCP is needed because IP gives almost no guarantees, but TCP doesn't actually add that many guarantees. Its chief function is to turn a packet protocol into a stream protocol. That means TCP guarantees a byte order; no bytes will arrive out of order. Don't count on more than that.
You see that protocols on top of TCP add extra checks. E.g. HTTP has the famous HTTP error codes, precisely because it can't rely on the error state from TCP. You probably have to do the same - or you can consider implementing your service as a HTTP service. "RESTful" refers to an API design methodology which closely follows the HTTP philosophy; this might be relevant to you.
The short answer to your 4th and 5th topics was taken as a shortcut from this answer (read the whole answer to get more info)
A socket has a send buffer and if a call to the send() function succeeds, it does not mean that the requested data has actually really been sent out, it only means the data has been added to the send buffer. For UDP sockets, the data is usually sent pretty soon, if not immediately, but for TCP sockets, there can be a relatively long delay between adding data to the send buffer and having the TCP implementation really send that data. As a result, when you close a TCP socket, there may still be pending data in the send buffer, which has not been sent yet but your code considers it as sent, since the send() call succeeded. If the TCP implementation was closing the socket immediately on your request, all of this data would be lost and your code wouldn't even know about that. TCP is said to be a reliable protocol and losing data just like that is not very reliable. That's why a socket that still has data to send will go into a state called TIME_WAIT when you close it. In that state it will wait until all pending data has been successfully sent or until a timeout is hit, in which case the socket is closed forcefully.
The amount of time the kernel will wait before it closes the socket,
regardless if it still has pending send data or not, is called the
Linger Time.
BTW: that answer also refers to the docs where you can see more detailed info

what does readable/writable mean in a socket file descriptor? And why regular files don't bother with that?

Since I'm new in learning libev recently, there's a readable/writable concept in a io_watcher that I don't quite understand. For my knowledge there's a parameter in linux system programming:
O_ASYNC
A signal (SIGIO by default) will be generated when the specified file
becomes readable or writable. This flag is available only for
terminals and sockets, not for regular files.
So, since a regular file won't bother with readable/writable, what readable/writable really mean in socket programming? And what measure did kernel do to find out whether a socket file descriptor is readable?
Considering the everything-is-a-file philosophy, does every socket descriptor with different descriptor number actually point to the same file? If so,can I consider the readable/writable problem is caused by the synchronisation?
OK it seems that I'v asked a silly question. What I really mean is that both socket and regular file read and write via file descriptor, so why socket descriptor got a readable/writable concept but regular file doesn't. Since EJP told me that this is because the buffer and each descriptor got their own pair of buffers, here's my conclusion: readable/writable concept is for buffers, if a buffer is empty, it's unreadable, while it is full, it's unwritable. readable and writable have nothing to do with synchronisation, and since regular file don't have a buffer, it is always readable and writable.
And there are more questions: when saying receive buffer, this buffer is not the same thing in int recv(SOCKET socket, char FAR* buf, int len, int flags);, right?
This question is specifically addressed in Unix Network Programming, Volume 1: The Sockets Networking API (3rd Edition) [W. Richard Stevens, Bill Fenner, Andrew M. Rudoff] (see it here. I'll add some minor edits for enhanced readability):
Under What Conditions Is a Descriptor Ready?
[...]
The conditions that cause select to return "ready" for sockets [are]:
1. A socket is ready for reading if any of the following four conditions
is true:
The number of bytes of data in the socket receive buffer is
greater than or equal to the current size of the low-water mark for
the socket receive buffer. A read operation on the socket will not block and will return a value greater than 0 (i.e., the data that is
ready to be read). [...]
The read half of the connection is closed (i.e., a TCP connection that
has received a FIN). A read operation on the socket will not block and
will return 0 (i.e., EOF).
The socket is a listening socket and the
number of completed connections is nonzero. [...]
A socket error is
pending. A read operation on the socket will not block and will return
an error (–1) with errno set to the specific error condition. [...]
2. A socket is ready for
writing if any of the following four conditions is true:
The number of bytes of available space in the socket send buffer is greater than or
equal to the current size of the low-water mark for the socket send
buffer and either: (i) the socket is connected, or (ii) the socket
does not require a connection (e.g., UDP). This means that if we set
the socket to nonblocking, a write operation will not block and will
return a positive value (e.g., the number of bytes accepted by the
transport layer). [...]
The write half of the connection is closed. A write
operation on the socket will generate SIGPIPE.
A socket using a non-blocking connect has completed the connection, or the connect has failed.
A socket error is pending. A write operation on the socket
will not block and will return an error (–1) with errno set to the
specific error condition. [...]
3.
A socket has an exception condition pending if there is out-of-band data
for the socket or the socket is still at the out-of-band mark.
[Notes:]
Our definitions of "readable" and "writable" are taken directly from the
kernel's soreadable and sowriteable macros on pp. 530–531 of TCPv2.
Similarly, our definition of the "exception condition" for a socket is
from the soo_select function on these same pages.
Notice that when an error occurs on a socket, it is marked as both
readable and writable by select.
The purpose of the receive and send low-water marks is to give the application control over how much data must be available for reading or how much space must be available for writing before select returns a readable or writable status. For example, if we know that our application has nothing productive to do unless at least 64 bytes of data are present, we can set the receive low-water mark to 64 to prevent select from waking us up if less than 64 bytes are ready for reading.
As long as the send low-water mark for a UDP socket is less than the send buffer size (which should always be the default relationship), the UDP socket is always writable, since a connection is not required.
A related read, from the same book: TCP socket send buffer and UDP socket (pseudo) send buffer
Readable means there is data or a FIN present in the socket receive buffer.
Writable means there is space available in the socket send buffer.
Files don't have socket send or receive buffers.
Considering the everything-is-a-file philosophy
What philosophy is that?
does every socket descriptor with different descriptor number actually point to the same file?
What file? Why would they point to the same anything? Question doesn't make sense.
I'm confused with one thing: when a socket is created, the descriptor is actually point to the receive and send buffers of the socket
It 'points to' a lot of things: a source address, a target address, a source port, a target point, a pair of buffers, a set of counters and timers, ...
not the file represent the net hardware.
There is no such thing as 'the file represent[ing] the net hardware', unless you're talking about the device driver entry in /dev/..., which is barely relevant. A TCP socket is an endpoint of a connection. It is specific to that connection, to TCP, to the source and target addresses and ports, ...

Resources