how do a client knows that the server closed its socket - sockets

I am using the following client code. After a successful connect(), if server shuts down all its connections , how will my client knows about this server shutdown ? Is there any way to listen for this kind of events from client side code?
int sfd = socket(PF_INET, SOCK_STREAM, tcp->p_proto);
struct sockaddr_in isa = getipa("localhost", 1025);
connect(sfd, (struct sockaddr*)&isa, sizeof isa);
ssize_t size = recv(sfd, (void*)buff, sizeof buff, MSG_WAITALL);
puts(buff);
printf("Enter message to send\n");
scanf("%s",sendMsg);
send(sfd, (void*) sendMsg, 255, MSG_NOSIGNAL)

recv() returns zero if this connection has been closed by the peer, or -1 with an errno setting if the connection has encountered an error.
This is documented.
You don't care about the other connections.
You could also consider adding error checking to the rest of your code. Every one of those system calls can encounter an error.

Related

Unix Domain Sockets datagram client with receive only

I have a simulator application which Unix Domain datagram sockets, which sends data to socket path for.ex /var/lib/XYZ.
sendto is returning -2 which is due to other end no peer is there(no other unix domian socket application is running)
I would like to write a datagram client/peer application using Unix Domain Sockets for receiving data from the server/simulator(which is sending data to /var/lib/XYZ).
My code is as follows:
#define BUF_SIZE 1024
#define SV_SOCK_PATH "/var/lib/XYZ"
#define SV_SOCK_PATH2 "/var/lib/ABC"
creation of Unix Domain sockets as below:
struct sockaddr_un svaddr, claddr;
....
sfd = socket(AF_UNIX, SOCK_DGRAM, 0);
if (sfd == -1)
printf("socket creation failed");
memset(&claddr, 0, sizeof(struct sockaddr_un));
claddr.sun_family = AF_UNIX;
strncpy(claddr.sun_path, SV_SOCK_PATH2, sizeof(claddr.sun_path) - 1);
if (bind(sfd, (struct sockaddr *) &claddr, sizeof(struct sockaddr_un)) == -1)
printf("bind failed");
/* Construct address of server */
memset(&svaddr, 0, sizeof(struct sockaddr_un));
svaddr.sun_family = AF_UNIX;
strncpy(svaddr.sun_path, SV_SOCK_PATH, sizeof(svaddr.sun_path) - 1);
while(1)
{
int len=sizeof(struct sockaddr_un);
numBytes = recvfrom(sfd, resp, BUF_SIZE, 0, (struct sockaddr*)&svaddr,&len);
if (numBytes == -1)
printf("recvfrom error");
else{
printf("no of bytes received from server: %d",(int)numBytes);
printf("Response %d: %s\n", (int) numBytes, resp);
}
}
remove(claddr.sun_path);
//exit(EXIT_SUCCESS);
}
but the program is not receiving anything...is there anything missed out??
When it comes to datagrams, there is no real client or server. Either side attempting to send is responsible for addressing datagrams to the other. So, in your code, the setup is all wrong. You're apparently attempting to direct the "server" (but really not a server, just the other peer) to send to you via svaddr but that isn't how it works.
For a datagram AF_UNIX socket, the sender either needs to explicitly specify the receiver's address in a sendto call, or it needs to first connect its socket to the receiver's address. (In the latter case, it can then use send instead of sendto since the peer address has been specified via connect.)
You can't specify the sending peer's address in the recvfrom call. The socket address argument in the recvfrom is intended to return to you the address from which the datagram was sent. Whatever is in that variable will be overwritten on successful return from recvfrom.
One way datagram peer programs are often structured: the "server" creates a well-known path and binds to it, then a "client" creates its own endpoint and binds to it (constructing a unique socket address for itself), then the client can sendto the server's well-known socket. The server, by using recvfrom to obtain the client's address along with the datagram, can then use sendto along with the address to return a message to the client (without needing to connect its socket). This provides a sort of client-server paradigm on top of the fundamentally equal-peer orientation of the datagram socket.
Finally, I should mention that it's usually a good idea to use fully specified pathnames to ensure both peers are using the same address even if started from different directories. (Normally, with AF_UNIX, the address is a path name in the file system used to "rendezvous" between the two peers -- so without a full path "some_socket" is "./some_socket" in the current working directory. Some systems, such as linux, also support an abstract "hidden" namespace that doesn't require a full path, but you must use an initial null byte in the name to specify that.)

Socket recv (blocking) fails with errno EAGAIN - resource temporarily unavailable

I am implementing a UNIX domain socket Inter Process communication code and I hit this error randomly - "errno 11: Resource temporarily unavailable" while trying to read from the socket. I use MSG_PEEK to read the number of bytes from the socket, and allocate bytes for receive buffer, and read the actual data.
The socket is a blocking socket and I do not have any code to have non-blocking (in all, accept/read/write). Any pointers on what could cause this on a blocking socket read? From the man page of MSG_PEEK, it seems like EAGAIN could be returned when socket is marked as non-blocking, using O_NONBLOCK.
The failure happens on the recv call below.
char temp_buffer[BUFFER_MAX];
num_bytes = recv(_connection_fd, &temp_buffer, BUFFER_SIZE_MAX, MSG_PEEK | MSG_TRUNC);
if (num_bytes < 0) {
LogError("Error reading from socket. %s", strerror(errno));
close(_connection_fd);
return -1;
}
.....
<Allocate memory>
.....
// Read actual data
num_bytes = read(_connection_fd, buffer, num_bytes);
...
<Send response back to client>
<Close socket descriptor>
It may also happen to blocking socket and blocking recv, if socket has timeout SO_RCVTIMEO option set (default is 0). BTW, did you consider select() before recv()?

Socket listen when using Single Client

I wrote a server code to run on my embedded platform...it listens to wifi clients and I have made provision to accept only one client connection at a time.
so I do,
sfd = socket(AF_INET, SOCK_STREAM, 0);
ret=bind(sfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
ret = listen(sfd,5);
while(1)
{
new_fd = accept(sfd,(struct sockaddr*)&client_addr,&len);
....
close(new_fd);
}
So in this case what I observe that only one client can send data...which is expected
But, Another client can connect to the socket simultaneouly...although the data from 2nd client is not processed.
So is this because of the listen(5) backlog parameter. So that I can simultaneously connect to 5 connections although I may not process them.
Please help me clarify.

errno 90 message too long on recv when ICMP destination unreachable packet arrives

I am reading data from a socket with recv function and keep getting error when I receive ICMP destination unreachable packet. I truly don't know where the problem is. I tried setting the socket to different options but none of them worked for me. I use RAW socket.
Here is my setsockopt:
setsockopt(sock, IPPROTO_IP, IP_HDRINCL, (char *)&optval, sizeof(optval))
optval is set to 1
here is my recv:
// read response from socket
if ((len = recv(sock, buffer, BUFFER_MAX, 0)) == -1)
fprintf(stderr,"Error with reading data - %d\n",errno);
BUFFER_MAX is defined as 65536
If somebody has met with similar problem, could you please explain me there is always errno code 90, when trying to recieve ICMP dest. unreachable packet? ECHO reply works fine.

how should I send messages from server to client in WinSock's UDP?

I am learning WinSock UDP. Most tutorials I've seen ask me to:
On server side:
SOCKET socked = socket(PF_INET, SOCK_DGRAM, 0)
bind(...);
for(;;) { recvfrom(..); }
On client side:
SOCKET socked = socket(PF_INET, SOCK_DGRAM, 0);
sendto(...);
But I wonder how can I do other way, send data from server to client. I don't know client's port (I figured out it vary every sendto call), and I want to be able to connect client behihd NAT to server and still recive data from server.
How it is done in modern games?
There are two questions in there.
Finding the address
The function recvfrom is declared:
int recvfrom(
__in SOCKET s,
__out char *buf,
__in int len,
__in int flags,
__out struct sockaddr *from, /* <--- */
__inout_opt int *fromlen /* <--- */
);
So you can use from and fromlen in sendto.
sendto(..., (SOCKADDR *)from, *fromlen);
NAT
The NAT-box should automatically allow the server to "answer" to the datagram sent by the client. So, the mere fact that the client sent a datagram causes the NAT-box to ephemerally (a few minutes?) open a port to allow traffic return.