sendto is not giving error on sending - c

Hi I have following code:
if ((fd = socket(PF_INET, SOCK_DGRAM, 0)) < 0)
{
perror("socket(UDP): ");
return 0;
}
family = AF_INET;
if((remote_server_ent = gethostbyname2(hptr, family)) == NULL )
{
perror("gethostbyname2");
return 0;
}
if (family == AF_INET)
{
sin = (struct sockaddr_in *) addr;
sin->sin_family = AF_INET;
sin->sin_port = htons(server_port);;
bcopy( (char *)remote_server_ent->h_addr, (char *)&(sin->sin_addr), remote_server_ent->h_length );
return (sizeof(struct sockaddr_in));
}
if (sendto(fd, msg_data_ptr, sizeof(Msg_data_hdr), 0, (struct sockaddr *)&sin, sizeof(struct sockaddr)) != sizeof(Msg_data_hdr))
{
fprintf(stderr, "Error in sending data to the server \n");
}
My APP is listing on port 7000 IP 127.0.0.1.
Now when i stop my application still sendto send the data, it does not give me error. I am always getting the written bytes equal the size of data which i am writting. How will i know if sending is failed or not???

It's UDP (SOCK_DGRAM), so you may never find out. If you need reliability guarantees, use TCP instead. If you're satisfied with a partial solution of just knowing when the receiving side is completely missing/unavailable, see here: ICMP "destination unreachable" packet on udp connected socket
The general idea is that you can receive ICMP "destination unreachable" errors if you connect() your UDP socket and then receive data on it (you will want to use select() or epoll() for this). In some scenarios you will find out that your messages are not making it to the other side...but in other scenarios you may not, because hey, it's UDP.

Related

UDP Multicast not receiving message

I am trying to make a simple UDP multicast example where a message is sent from one program and received from the other but right now the output is only:
Connected
Message Sent
and
bind
setup multicast
Can someone please tell me what I am missing so that I can receive the message successfully? Thank you!! Here are the codes in full:
int main(int argc, char *argv[])
{
int udp_socket_info;
struct sockaddr_in udp_server;
char* message="test";
//create socket
udp_socket_info = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_socket_info == -1) {
puts("Could not create socket");
}
//assign local values
udp_server.sin_addr.s_addr = inet_addr("225.0.0.37"); //multicast address
udp_server.sin_family = AF_INET;
udp_server.sin_port = htons( 1100 );
//checks connection
if (connect(udp_socket_info, (struct sockaddr *)&udp_server, sizeof(udp_server)) < 0) {
perror("Connection error");
}
puts("Connected");
//sends message
if( sendto(udp_socket_info , message , strlen(message) , 0, (struct sockaddr *)&udp_server, sizeof(udp_server)) < 0) {
perror("Send failed");
}
puts("Message Sent");
}
and the second program is
int main(int argc, char *argv[])
{
//initialize udp socket and structures
int udp_socket_info;
struct sockaddr_in udp_server;
struct sockaddr addr;
struct ip_mreq mreq;
socklen_t fromlen;
fromlen = sizeof addr;
char incoming_message[100];
//create udp socket
udp_socket_info = socket(AF_INET, SOCK_DGRAM, 0);
if (udp_socket_info == -1) {
puts("Could not create socket");
}
// set up
memset((char*)&udp_server,0,sizeof(udp_server));
udp_server.sin_family=AF_INET;
udp_server.sin_port = htons( 1100 );
udp_server.sin_addr.s_addr = inet_addr("192.168.0.100"); //local address
// bind
if (bind(udp_socket_info,(struct sockaddr *)&udp_server, sizeof(udp_server)) < 0) {
perror("bind error");
exit (1);
}
puts("bind");
// use setsockopt() to join multicast group
mreq.imr_multiaddr.s_addr=inet_addr("225.0.0.37"); //multicast address
mreq.imr_interface.s_addr= htonl(INADDR_ANY); //can use local address here too
if (setsockopt(udp_socket_info, IPPROTO_IP,IP_ADD_MEMBERSHIP, &mreq, sizeof(mreq)) < 0) {
perror("setsockopt");
exit (1);
}
puts("setup multicast");
//Receive an incoming message
if( recvfrom(udp_socket_info, incoming_message , sizeof(incoming_message), 0, &addr, &fromlen) < 0) {
puts("Received failed");
exit (1);
}
puts("Message received");
puts(incoming_message);
}
You should bind the receiving socket to INADDR_ANY, not a local interface address. Otherwise you run the risk that the sender is out there via a different route and can't reach your socket. On some platforms you can bind it to the multicast address itself.
NB when you get an error it isn't sufficient to print a message of your own devising. The message must contain the errno, or the result of strerror(). For example, call perror().
Your receiver should not bind to a local address. It should instead bind to either INADDR_ANY or the multicast address you intend on joining. Binding to a local address breaks multicast on Linux systems.
Note that if you bind to a multicast address, this means you'll only receive packets for that multicast address. If you want to receive from multiple multicast addresses or if you also want to receive unicast packets then you need to bind to INADDR_ANY.
When joining a multicast group, using INADDR_ANY causes you to join the specified group on the default network interface. It's generally a good idea to explicitly specify an interface.
As EJP mentioned, you should always use perror to print error messages from any system or library call to ensure that a meaningful error message is printed.
Wireshark is an important tool for programs such as this. It helps you ensure that packets are going out and coming in the network interfaces you expect.
Also, if the sender and receive are on different network segments, you'll need to set the TTL via the IP_MULTICAST_TTL socket option. You also need to make sure that any routers between them are configured to pass multicast traffic.

udp sendto can not send the whole txt file in a real time

I have really strange problem. I made server and client communicating using unicast sockets.
Server is sending text file in blocks of 512 bytes and client is receiving and writing blocks to a txt file. But I noticed that without sleep(1) function on both sides server can not send the whole file. For example the file is made of 2939 blocks and in wireshark I can see just 1827, 2005, 1657 but never the whole file , all 2939 blocks ? Why ? Packets are not lost because server and client are connected via ethernet cable to the router and are on the same local network.
Can you give me directions and advices how to solve this problem? Here is the code :
#includes...
#define BUF_SIZE 512
#define PORT 1234
#define IP "192.168.0.103" // address of a client
static int val = 1;
int sent=0;
int main() {
struct sockaddr_in client,server;
char tmp[BUF_SIZE];
int n,s,fd;
ssize_t numRead;
int rv,optval=1;
if((s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP))<0){
printf("Opening datagram socket error",strerror(errno));
return 1;
}else{
printf("Opening datagram socket....OK.\n");
}
if(setsockopt(s, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval)) == -1){
printf("Setsockopt error: %s", strerror(errno));
return 1;
}
memset((char *) &server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT);
memset((char *) &client, 0, sizeof(client));
client.sin_family = AF_INET;
client.sin_addr.s_addr = inet_addr(IP);
client.sin_port = htons(PORT);
if(bind(s, (struct sockaddr*)&server, sizeof(server))){
printf("Binding datagram socket error %s",strerror(errno));
close(s);
return 1;
}
if((fd = open("udp_text.txt", O_RDONLY , 0777))== -1){
printf("Error while opening txt file %s!\n",strerror(errno));
return 1;
}
while (1) {
if((numRead = read(fd,tmp,512)) == 512){
tmp[numRead]='\0';
rv = sendto(s,tmp,sizeof(tmp),0, (struct sockaddr *) &client, sizeof(struct sockaddr_in));
memset(tmp,0,BUF_SIZE);
}else{
rv = sendto(s,tmp,sizeof(tmp),0, (struct sockaddr *) &client, sizeof(struct sockaddr_in));
printf("EOF !\n");
return 1;
}
}
close(s);
return 0;
}
Thx
Since not all the packets show up in wireshark, I would guess that the sender is running out of network packet buffer space in the operating system. UDP can not only suffer packet loss from transmission failures but also if any routing component runs out of capacity and is forced to drop the packet because it is too busy. This includes the local internet protocol stack.
As a start, check the error code from sendto(). If the local operating system is to blame then it will likely have the courtesy of reporting an error.
Update: No error from sendto(), well then, no easy fix.
One final note of caution/advice. Even direct ethernet connections between hosts does not guarantee packets will always get through. If you depend on the file data getting transferred reliably then you'll need to add some kind of acknowledgement response from the receiver to confirm successful reception of the data. And associated logic in the sender to retransmit data as required.
That's a fair bit of work and why you might rather switch to TCP sockets which do all that for you.
If you are going to send files over UDP, at least use an existing protocol that is designed for that purpose, like Trivial FTP (see RFC 1350). It offers buffer size control and safety from dropped packets.

getpeername() won't return a correct port but it returns a correct address of remote host socket language C

I would like to ask about the getpeername() function since it returns data as the title states. I tried to get value directly from accept() function, and the result also happens the same. Value of port seems to appear randomly even though value of address is correct(address is 127.0.0.1 since I run multi-processes on an only machine). The return code of getpeername() is 0 (status = 0). I'm using gcc version 4.8.1. I write a peer 2 peer chat application without server. The following is my code:
struct sockaddr_in addr;
socklen_t addr_len;
int tempPort, serverSockfd;
char test[100];
// Get serverSockfd successfully....
serverSockFd = initializeSock(PORT) // In this function I initialize socket(), bind() and listen(), serverSockFd is returned by the value of socket()
addr_len = sizeof addr;
newSock = accept(serverSockfd, (struct sockaddr *)&addr, &addr_len);
tempPort = ntohs(addr.sin_port);
inet_ntop(AF_INET, &(addr.sin_addr), test, sizeof test);
printf("tempPort\t%d\n", tempPort);
printf("test\t%s\n", test);
addr_len = sizeof addr;
if ((status = getpeername(newSock, (struct sockaddr *) &addr, &addr_len)) != 0){
printf("getpeername() error!\n");
}
tempPort = ntohs(addr.sin_port);
inet_ntop(AF_INET, &(addr.sin_addr), test, sizeof test);
printf("tempPort\t%d\n", tempPort);
printf("test\t%s\n", test);
Thanks very much for any your comment. Here is a partial code in initializeSock():
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd < 0)
{
perror("SocketInit(): socket() error!\n");
exit(1);
}
ret_val = setsockopt(sd, SOL_SOCKET, SO_REUSEADDR, (char*) &flag, sizeof(flag));
if(ret_val == -1)
{
perror("SocketInit(): setsockopt(SO_REUSEADDR) error!\n");
exit(1);
}
gethostname(hostname,100);
host_entry = gethostbyname(hostname);
addr.sin_family = AF_INET;
addr.sin_port = htons(port);
addr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list));
ret_val = bind(sd, (struct sockaddr*) &addr, sizeof(addr));
if(ret_val == -1)
{
perror("SocketInit(): bind() error!\n");
printf("For port:%d\n",port);
exit(1);
}
....
return sd;
This is the code to connect to server part of a peer. ConnectSock(portOfPeerA):
sd = socket(AF_INET, SOCK_STREAM, 0);
if(sd < 0)
{
perror("ConnectToServer(): socket() error!\n");
exit(1);
}
if (port != 0) {
addr.sin_family = AF_INET;
addr.sin_port = htons(portOfPeerA);
addr.sin_addr.s_addr = inet_addr(inet_ntoa(*(struct in_addr *)*host_entry->h_addr_list));
// Do I need to bind() the port of peer B when it would like to connect to peer A?
ret_val = connect(sd, (struct sockaddr*)&addr, sizeof(addr));
if(ret_val == -1)
{
printf("Error connect());
exit(1);
}
...
I don't know which port you accept from the peer, but if the peer is connecting to your server (e.g. then one calling accept) it will connect from a (more or less) random port, that's how TCP works. It connects from a fixed port only if the peer explicitly binds to that port before connecting.
This means, that the peers originating port is not defined on the server side (where your code fragments are from) but on the client side (the side which calls connect and where you only do connect but no bind).
But, please note that it might give problems with repeated connections, if both client and server use fixed IP and ports, because then you will get the same 4-tupel in TCP which defines the connections for repeated connections and thus go into all this trouble with the various TIME_WAIT states. So it is better to let the client just pick an available port and not force it to use a specific one.
getpeername() (and accept()) reports the IP and port that the remote party is locally bound to on its end. If the remote party is a client that did not call bind() before calling connect() then connect() performs an implicit bind to a random available port. That is what you are seeing, and that it typical usage. Most clients do not need to call bind() before connect(), but there are use cases where doing so is necessary, so don't rule it out.

UDP Client shows 'UDP Connected' while no UDP Server running on localhost

What is wrong with the following function ??
It should throw an error as I have no UDP server running on localhost.
int openUdpSocket(int port) {
int sock,sin_size;
struct sockaddr_in server_addr;
memset(&server_addr, 0, sizeof(server_addr));
struct hostent *host;
host= (struct hostent *) gethostbyname((char *)"127.0.0.1");
if ((sock = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(port);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8);
sin_size = sizeof(struct sockaddr);
Now the Following part causing trouble : -
int error = connect(sock, (struct sockaddr *)&server_addr, sizeof(server_addr));
if(error < 0){
printf("Connection error\n");
exit(-1);
}
if (verbose)
printf("UDP connected\n");
return sock;
}
Output:
udit#mylaptop:~/Desktop/benchmark$ ./a.out
UDP connected
Note that I have created a similar function for TCP and the same thing is working fine with TCP that means when no TCP Server running it shows connection error and when TCP Server running then TCP Connected
The UDP Client mentioned above needs to receive response in form of some status codes in future. SO, Do I need to use bind() function here ??
You need to lookup what connect() does for a SOCK_DGRAM socket. It doesn't imply the existence of a peer. It only establishes an inbound and outbound IP address filter. See man 2 connect.
for UDP communication you need to use Sendto and Receivefrom functions,
bind and connect are not required for UDP communication.
try to search about this two functions and use them. :)

DHCP client doesnt receive response on port 68

I have used wireshark to see the DHCP packet structure. Now I have created a DHCPDISCOVER request and stored it in 'message'. I then broadcast it on the network.
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sockfd < 0) {
perror("socket");
exit(1);
}
setsockopt(sockfd,SOL_SOCKET,SO_BROADCAST, &on,sizeof(on));
setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR, &on,sizeof(on));
bzero(&cliaddr, sizeof(cliaddr));
cliaddr.sin_family = AF_INET;
cliaddr.sin_addr.s_addr = htonl(INADDR_ANY);
cliaddr.sin_port = htons(68);
if (bind(sockfd, (struct sockaddr *) &cliaddr, sizeof(cliaddr)) < 0) {
perror("bind");
exit(1);
}
bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr("255.255.255.255");
addr.sin_port = htons(67);
cnt = sendto(sockfd, message, sizeof(message), 0,(struct sockaddr *) &addr, sizeof(addr));
if (cnt < 0) {
perror("sendto");
exit(1);
}
addrlen = sizeof(servaddr);
cnt = recvfrom(sockfd, reply, sizeof(reply), 0,(struct sockaddr *) &servaddr, &addrlen);
if (cnt < 0) {
perror("recvfrom");
exit(1);
}
printf("\nReply Received\n");
I run this program and analyze the packets sent and received using wireshark. I see that a DHCPDISCOVER packet is sent on port 67 and a DHCPOffer packet is received on port 68 in the wireshark window. My client sends the packet fine but does not receive this packet and it blocks on recvfrom call. What is going wrong?
You need to put your receive out before you send the packet request, or else the response probably comes back before you are ready to receive it.
Also, is the response broadcast? If not, and you don't currently have an IP address assigned to your machine, then you're going to have some trouble receiving it because your host will filter received packets by IP address won't know that the response is destined for it (even though the link layer address matches), so it'll not deliver it.
But my guess is it's the first problem. You'll have to either use threads or do a non-blocking receive, or else your receive will block and thus you'll never getting around to sending the request.
Well i disagree with the above answer.. recvfrom should be able receive both the packets.
Here problem lies because ,port no is within the range of 1000. typically , these packets are filtered by linux kernel(iptables) and not sent to. user application.
https://bugzilla.redhat.com/show_bug.cgi?id=983672

Resources