Why is Connect() returning a negative value? - c

#include<io.h>
#include<stdio.h>
#include<winsock2.h>
#include <ctype.h>
#include<string.h>
#include<strings.h>
#define MY_PORT 8989 //defining the port for the socket
#define MAXBUF 256
int main(int argc , char *argv[])
{
//char str[MAXBUF];
int a;
WSADATA wsa;
SOCKET sockfd , clientfd; //SOCKET is a data type. We initialize two variables of the data type Socket here
struct sockaddr_in self; //structure for the family,port and IP address of the socket (Socket descriptors)
char buffer[MAXBUF]; // this is a character array that will receive the message from the client and we will use this to manipulate
//char message[MAXBUF];
printf("\nInitialising Winsock...");
if (WSAStartup(MAKEWORD(2,2),&wsa) != 0) //WSASTARUP is used to tell windows to get ready for a connection and if it returns a value 0, windows is ready
{
printf("Failed. Error Code : %d",WSAGetLastError());
return 1;
}
printf("Initialised.\n");
/*---create streaming socket---*/
if ( (sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0 ) //socket is created using a function called socket
//using AF_INET means that we are using TCP/IP family
//the if statement here checks whether or not the value returned by the socket is negative or not. If it is negative that means there is some sort of an error
{
perror("Socket");
exit(errno);
}
printf("Socket created.\n");
self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&self,'\0', sizeof(self));
/*The connect function below is used to establish a connection between the client and the server*/
if (connect(sockfd, (struct sockaddr*)&self, sizeof(self)) <0)
{
printf("connection with the server failed...\n");
exit(0);
}
else
printf("connected to the server..\n");
printf("Please enter message: ");
memset(buffer, 0, sizeof (buffer));
fgets(buffer, MAXBUF, stdin); //fgets is used here to get whatever is inside the buffer
while (1)
{
/*struct sockaddr_in client_addr;
int addrlen=sizeof(client_addr);*/
/*---accept a connection (creating a data pipe)---*/
a= write(sockfd, buffer, sizeof(buffer));
if(a<0){
printf("Error");
}
// a= recv(clientfd, buffer, MAXBUF, 0);
//accept(clientfd, (struct sockaddr*)&client_addr, &addrlen);
a= read(sockfd, buffer, sizeof(buffer));
if(a<0){
printf("Error");
}
if (strncmp("QUIT", buffer, 4) == 0) {
printf("Server Exit...\n");
break;
}
}
close(sockfd); //close the sockfd
WSACleanup(); // windows socket is cleaned up
return 0;
}
The code works completely fine but for some reason, which I can't wrap my head around the connect function keeps on returning a negative value, or at least a value that is not zero. The server I am using with this client works for other clients, so I know for a fact that there is nothing wrong with it.
Your help will be much appreciated.

self.sin_family = AF_INET;
self.sin_port = htons(MY_PORT);
self.sin_addr.s_addr = htonl(INADDR_ANY);
memset(&self,'\0', sizeof(self));
In this code you set all the values of self and then you just clear self with memset. I'm pretty sure that this makes no sense and likely is the cause of the error you see, i.e. no useful parameters given for connect.
Even without this erroneous memset the code does not make much sense: you are trying to connect to INADDR_ANY but there is no such IP address to connect to. INADDR_ANY means on the server side to listen on every address of the machine - on the client side it cannot be used but instead the real IP address have to be used, like 127.0.0.1 for localhost.

Related

message from client to server in C

I have such a task, I need to write the “client” code so that the message from the “client” is sent to the server (which was created by my teacher, ip “127.0.0.1”). After the message arrives at the server (for example, “Nursultan Nazarbayev”, the server will reply “ok” and the client should send “quit”)
I'm just learning C. How to make a break with the server? I wanted to send "quit", but this did not work, there was a constant error, how can I do this?
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
int main (int argc, char **argv)
{
char message[2048];//=(char*)malloc(sizeof(char));// transmission message
char buf[sizeof(message)];
int port,ch;
//----------------------------------------------------------------------------
if(argc!=3){
printf("Wrong number of arguments!\nThere must be 2 arguments (Port, server ip-address)!\n");
exit(0);
}
int sock; // socket descriptor
struct sockaddr_in addr; // structure with address
struct hostent* hostinfo;
port = atoi(argv[1]);
hostinfo = argv[2];
sock = socket(AF_INET, SOCK_STREAM, 0); // create TCP socket
if(sock < 0)
{
perror("socket");
exit(1);
}
// Specify server parameters
addr.sin_family = AF_INET; // Internet domains
addr.sin_port = htons(port); // or any other port ...
addr.sin_addr.s_addr=inet_addr("hostinfo");
// addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
//addr.sin_addr.s_addr = inet_addr(host_ip);
if(connect(sock, (struct sockaddr *)&addr, sizeof(addr)) < 0) // establishing a connection to the server
{
perror("Connection");
exit(2);
}
while(1){//WHILE <---
//----------------------------------------------------------------------------
printf("Enter a message to the server (To exit: quit): ");
if (!strcmp(gets(message), "quit")){close(sock);return 0;}
//----------------------------------------------------------------------------
printf("sending a message to the server...\n");
send(sock, message, sizeof(message), 0); // sending a message to the server
int bytes_read = 0;
printf("Message Waiting\n");
bytes_read = recv(sock, buf, sizeof(message), 0);
printf("received %d bytes\tMessage: %s\n", bytes_read, buf); // receiving a message from the server
}//END_WHILE
return 0;
}
This probably is wrong:
addr.sin_addr.s_addr=inet_addr("hostinfo");
You are passing the literal string, "hostinfo" to the inet_addr() function. Meanwhile, you have a variable named hostinfo, to which you assign a string value, but you never use it anywhere in the program.
Maybe you meant to do this instead:
addr.sin_addr.s_addr=inet_addr(hostinfo);
P.S., I like long, descriptive names. If that was my program, the name of the variable would be something like, server_address_as_string.

TCP cannot detect closed socket in client

I have server that just connects to a client and right after that disconnects, while client tries to send an integer to a closed socket (scanf is to ensure server closese it first). I use send with MSG_NOSIGNAL and check for EPIPE but the flag is not set. I think result should have printed value of -1, or 0, but it is equal to 1, because I am writing on already closed socket. Can someone explain that?
Server Code:
#define QUEUE_LENGTH 5
#define PORT_NUM 10002
#define BUFFER_SIZE 512000
int main(int argc, char *argv[]) {
int sock, msg_sock;
struct sockaddr_in server_address;
struct sockaddr_in client_address;
socklen_t client_address_len;
sock = socket(PF_INET, SOCK_STREAM, 0); // creating IPv4 TCP socket
if (sock < 0)
syserr("socket");
server_address.sin_family = AF_INET; // IPv4
server_address.sin_addr.s_addr = htonl(
INADDR_ANY); // listening on all interfaces
server_address.sin_port = htons(PORT_NUM);
// bind the socket to a concrete address
if (bind(sock, (struct sockaddr *) &server_address,
sizeof(server_address)) < 0)
syserr("bind");
// switch to listening (passive open)
if (listen(sock, QUEUE_LENGTH) < 0)
syserr("listen");
printf("accepting client connections on port %hu\n",
ntohs(server_address.sin_port));
for (;;) {
client_address_len = sizeof(client_address);
msg_sock = accept(sock, (struct sockaddr *) &client_address,
&client_address_len);
if (msg_sock < 0)
syserr("accept");
printf("ending connection\n");
if (close(msg_sock) < 0) {
printf("ErrorClosingSocket\n");
break;
}
continue;
}
return 0;
}
Client code:
int sendSomething(void *to_send, int socket, uint32_t length) {
if (send(socket, to_send, length, MSG_NOSIGNAL) !=
length) {
if (errno == EPIPE) // Sending on closed connection
return 0;
return -1;
}
return 1;
}
int main(int argc, char *argv[]) {
int sock;
struct addrinfo addr_hints;
struct addrinfo *addr_result;
int err;
if (argc != 3)
fatal("Usage: %s host port\n", argv[0]);
// 'converting' host/port in string to struct addrinfo
memset(&addr_hints, 0, sizeof(struct addrinfo));
addr_hints.ai_family = AF_INET; // IPv4
addr_hints.ai_socktype = SOCK_STREAM;
addr_hints.ai_protocol = IPPROTO_TCP;
// argv[1] is localhost and argv[2] is 10002
err = getaddrinfo(argv[1], argv[2], &addr_hints, &addr_result);
if (err == EAI_SYSTEM) // system error
syserr("getaddrinfo: %s", gai_strerror(err));
else if (err != 0) // other error (host not found, etc.)
fatal("getaddrinfo: %s", gai_strerror(err));
// initialize socket according to getaddrinfo results
sock = socket(addr_result->ai_family, addr_result->ai_socktype,
addr_result->ai_protocol);
if (sock < 0)
syserr("socket");
// connect socket to the server
if (connect(sock, addr_result->ai_addr, addr_result->ai_addrlen) < 0)
syserr("connect");
freeaddrinfo(addr_result);
int result;
scanf("%d", &result);
uint16_t test;
test = htons(1);
result = sendSomething(&test, sock, sizeof(test));
printf("result:%d\n", result);
if (close(sock) < 0) {
printf("ErrorClosingSocket\n");
}
return 0;
}
Note: Fatal and Syserr are just for reporting errors
That's the way TCP works. When the server closes the socket, then a FIN is sent to the client. This only signals, that the server will not send any more data. It does not necessarily mean, that it does not want to receive more data.
Thus, the client can call send() on the socket without the OS reporting an error. If the server indeed closed the whole socket, then it will send a TCP reset packet as a response to incoming data indicating that condition. Now, future operations on the socket (write/close) will indicate an error.
It is indeed possible for the server (or any peer) to only shutdown the connection half-way (the reading or the writing side) with the syscall shutdown(). If the server shuts down the connection for writing, the same thing happens on the network as if the server closed the whole connection with close(). It is the duty of a higher level protocol to determine, when a connection should be closed for each side.
If you want to make sure, that all data that you sent was indeed acknowledged by the peer, you can use the SO_LINGER socket option. But a more common way is, to make this sure as a part of the communication protocol, i.e. one part requests to shutdown the connection on a higher level (for example, the smtp QUIT command) and the peer reacts on it by closing the tcp connection.

Send UDP packet with fixed source port number using getaddrinfo and bind

Using BJ's talker.c code as a template:
http://beej.us/guide/bgnet/examples/talker.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#define SERVERPORT "4950" // the port users will be connecting to
int main(int argc, char *argv[])
{
int sockfd;
struct addrinfo hints, *servinfo, *p;
int rv;
int numbytes;
struct sockaddr_storage their_addr;
socklen_t addr_len;
addr_len = sizeof their_addr;
if (argc != 3) {
fprintf(stderr,"usage: talker hostname message\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and make a socket
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("talker: socket");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "talker: failed to create socket\n");
return 2;
}
if ((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0,
p->ai_addr, p->ai_addrlen)) == -1) {
perror("talker: sendto");
exit(1);
}
freeaddrinfo(servinfo);
printf("talker: sent %d bytes to %s\n", numbytes, argv[1]);
//============== Added Code for recvfrom() (pseudocode-ish) =============
if ((numbytes = recvfrom(sockfd, buf, MAXBUFLEN , 0, (struct sockaddr *)&their_addr, &addr_len)) == -1)
{
close(sockfd);
perror("talker: recvfrom");
exit(1);
}
close(sockfd);
printf("Got packet\n");
//============== End Added Code for recvfrom() =============
close(sockfd);
return 0;
}
I have a requirement whereby the client UDP process that talks to the server must use a fixed, known source port number. In this case, assume it's SERVERPORT (4950). The server then responds to that port number. Yes, this is unusual as most servers respond to the ephemeral port number that the system assigns to the sender.
After sending a packet using sendto(), I listen for a response using recvfrom(). That's the (pseudo)code I added in the above example.
All my searches online point to using bind() but that code is usually on the server side. I haven't found a way to bind on the client side using the modern getaddrinfo() method. I tried to add a bind() right after the socket() setup but that wouldn't work because p is a server-side structure (derived from the hints structure that uses the server IP address) and I get a bind Error:
Error 99 (Cannot assign requested address)
code added:
bind(sockfd, p->ai_addr, p->ai_addrlen)
I want to do this in a way that will work for both IPv4 and IPv6.
I've seen other examples whereby a local/source sockaddr_in structure is filled out with the client's information and that is used in the bind, but those are IPv4 or IPv6 specific.
Can someone please show me how to properly update the talker.c code to sendto() and recvfrom() a UDP server using a fixed source port number? Assume that the server is immutable.
The server then responds to that port number. Yes, this is unusual
There is nothing unusual about that. This is how most UDP servers are meant to work. They always respond to the sender's port. They have no concept whether that port is fixed or ephemeral, that is for the sender to decide. Unless a particular protocol dictates that responses are to be sent to a different port, which is not common.
All my searches online point to using bind()
Correct, that is what you need in this situation.
but that code is usually on the server side.
There is nothing preventing a client from using bind().
I haven't found a way to bind on the client side using the modern getaddrinfo() method.
It is the exact same as on the server side, except that you have to bind to a specific IP address, you can't bind to 0.0.0.0 or ::0 like you can with a server socket.
I tried to add a bind() right after the socket() setup but that wouldn't work
Yes, it does. The problem is that you are using the SAME IP address for both binding and sending, and that will not work. You need to bind to the CLIENT's IP address and then send to the SERVER's IP address.
because p is a server-side structure (derived from the hints structure that uses the server IP address)
You are misusing p. You can't bind() a client socket to the server's IP address (you need to use connect() for that instead). You need to bind() a client socket to an IP address that is local to the client's machine. Just like you have to bind() a server socket to an IP address that is local to the server machine.
Remember, a socket is associated with a pair of IP addresses. bind() establishes the socket's LOCAL IP address. connect() establishes the socket's REMOTE IP address.
I want to do this in a way that will work for both IPv4 and IPv6.
You can't create a single client socket for both protocols. You need separate sockets for each protocol (on the server side, you can create a single socket for both protocols, if your platform supports dual-stack sockets).
I've seen other examples whereby a local/source sockaddr_in structure is filled out with the client's information and that is used in the bind, but those are IPv4 or IPv6 specific.
Yes, because you will be sending a packet using EITHER IPv4 OR IPv6, you can't send a packet using both protocols at the same time (a dual-stack socket can receive packets from either protocol, though).
Can someone please show me how to properly update the talker.c code to sendto() and recvfrom() a UDP server using a fixed source port number . Assume that the server is immutable
Try something like this:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <stdbool.h>
#define LOCALPORT "4950" // the port users will be sending from
#define SERVERPORT "4950" // the port users will be connecting to
#define MAXBUFLEN 65535
int main(int argc, char *argv[])
{
int sockfd;
struct addrinfo hints, *myinfo, *servinfo, *pserv, *plocal;
int rv;
int numbytes;
char buf[MAXBUFLEN];
char ipstr[INET6_ADDRSTRLEN];
fd_set readfds;
struct timeval tv;
bool stop = false;
if (argc < 3) {
fprintf(stderr, "usage: talker destaddr message [localaddr]\n");
return 1;
}
// get all of the server addresses
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_protocol = IPPROTO_UDP;
if ((rv = getaddrinfo(argv[1], SERVERPORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 2;
}
// loop through all the server addresses
for(pserv = servinfo; (pserv != NULL) && (!stop); pserv = pserv->ai_next) {
memset(ipstr, 0, sizeof(ipstr));
switch (pserv->ai_family)
{
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in*)pserv->ai_addr)->sin_addr), ipstr, INET_ADDRSTRLEN);
break;
case AF_INET6:
inet_ntop(AF_INET6, &(((struct sockaddr_in6*)pserv->ai_addr)->sin6_addr), ipstr, INET6_ADDRSTRLEN);
break;
}
printf("talker: trying to send message to %s\n", ipstr);
// get all of the matching local addresses
memset(&hints, 0, sizeof hints);
hints.ai_family = pserv->ai_family;
hints.ai_socktype = pserv->ai_socktype;
hints.ai_protocol = pserv->ai_protocol;
if ((rv = getaddrinfo(argc > 3 ? argv[3] : NULL, LOCALPORT, &hints, &myinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
continue;
}
// loop through all the local addresses, sending the
// message from each one until a reply is received
for(plocal = myinfo; (plocal != NULL) && (!stop); plocal = plocal->ai_next) {
if ((sockfd = socket(plocal->ai_family, plocal->ai_socktype, plocal->ai_protocol)) == -1) {
perror("socket");
continue;
}
memset(ipstr, 0, sizeof(ipstr));
switch (plocal->ai_family)
{
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in*)plocal->ai_addr)->sin_addr), ipstr, INET_ADDRSTRLEN);
break;
case AF_INET6:
inet_ntop(AF_INET6, &(((struct sockaddr_in6*)plocal->ai_addr)->sin6_addr), ipstr, INET6_ADDRSTRLEN);
break;
}
printf("talker: binding to %s\n", ipstr);
if (bind(sockfd, plocal->ai_addr, plocal->ai_addrlen) == -1) {
perror("bind");
close(sockfd);
continue;
}
// make sure this server address is the only one we talk to
if (connect(sockfd, pserv->ai_addr, pserv->ai_addrlen) == -1) {
perror("connect");
close(sockfd);
continue;
}
if ((numbytes = send(sockfd, argv[2], strlen(argv[2]), 0)) == -1) {
perror("send");
close(sockfd);
continue;
}
printf("talker: sent %d bytes\n", numbytes);
FD_ZERO(&readfds);
FD_SET(sockfd, &readfds);
tv.tv_sec = 5;
tv.tv_usec = 0;
rv = select(sockfd+1, &readfds, NULL, NULL, &tv);
if (rv == -1)
{
perror("select");
close(sockfd);
continue;
}
if (rv == 0)
{
printf("talker: no reply for 5 seconds\n");
close(sockfd);
continue;
}
if ((numbytes = recv(sockfd, buf, MAXBUFLEN, 0)) == -1)
{
perror("recv");
close(sockfd);
continue;
}
printf("talker: received %d bytes\n", numbytes);
close(sockfd);
stop = true;
break;
}
freeaddrinfo(myinfo);
}
freeaddrinfo(servinfo);
close(sockfd);
if (!stop) {
fprintf(stderr, "talker: failed to communicate with server\n");
return 3;
}
return 0;
}

UDP Socket Programming in C: 2 Clients and 1 Server

Im very new to network programming. I have a UDP client/server that sends a message to a server in lower or uppercase. The server receives the message and relays it back with switches cases. I cant figure out how I would instead of relaying it back to the first client, sending it to client2. heres my code.
Server:
/*
Simple udp server
*/
#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
#include<ctype.h>
#define BUFLEN 512 //Max length of buffer
#define PORT 8888 //The port on which to listen for incoming data
void die(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_me, si_other, si_other2;
int s, i, slen = sizeof(si_other) , recv_len;
char buf[BUFLEN];
//create a UDP socket
if ((s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1)
{
die("socket");
}
// zero out the structure
memset((char *) &si_me, 0, sizeof(si_me));
si_me.sin_family = AF_INET;
si_me.sin_port = htons(PORT);
si_me.sin_addr.s_addr = htonl(INADDR_ANY);
//bind socket to port
if( bind(s , (struct sockaddr*)&si_me, sizeof(si_me) ) == -1)
{
die("bind");
}
//keep listening for data
while(1)
{
printf("Waiting for data...");
fflush(stdout);
//try to receive some data, this is a blocking call
if ((recv_len = recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen)) == -1) // read datagram from server socket
{
die("recvfrom()");
}
//print details of the client/peer and the data received
printf("Received packet from %s:%d\n", inet_ntoa(si_other.sin_addr), ntohs(si_other.sin_port)); printf("Data: %s\n" , buf);
//now reply to server socket/the client with the same data
if (sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen) == -1)
{
die("sendto()");
}
}
close(s);
return 0;
}
The Client:
/*
Simple udp client
*/
#include<stdio.h> //printf
#include<string.h> //memset
#include<stdlib.h> //exit(0);
#include<arpa/inet.h>
#include<sys/socket.h>
#include<ctype.h>
#define SERVER "192.x.x.x"
#define BUFLEN 512 //Max length of buffer
#define PORT 8888 //The port on which to send data
void die(char *s)
{
perror(s);
exit(1);
}
int main(void)
{
struct sockaddr_in si_other;
int s, s2, i, slen=sizeof(si_other);
char buf[BUFLEN];
char message[BUFLEN];
if ( (s=socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == -1) // create a client socket
{
die("socket");
}
memset((char *) &si_other, 0, sizeof(si_other));
si_other.sin_family = AF_INET;
si_other.sin_port = htons(PORT);
if (inet_aton(SERVER , &si_other.sin_addr) == 0) // Create datagram with server IP and port.
{
fprintf(stderr, "inet_aton() failed\n");
exit(1);
}
while(1)
{
printf("Enter message : ");
gets(message);
int a;
char message2[BUFLEN];
for(a=0;a<=BUFLEN-1;a++)
{
if(message[a] >= 97 && message[a] <= 122)
message2[a] = toupper(message[a]);
else
message2[a] = tolower(message[a]);
}
if (sendto(s, message2, strlen(message2) , 0 , (struct sockaddr *) &si_other, slen)==-1)
{
die("sendto()");
}
//receive a reply and print it
//clear the buffer by filling null, it might have previously received data
memset(buf,'\0', BUFLEN);
//try to receive some data, this is a blocking call
if (recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen) == -1) // read datagram from client socket
{
die("recvfrom()");
}
puts(buf);
}
close(s);
return 0;
}
Since this has 21K views with no explicit answer, and it is basic understanding of coding for UDP.. I will give it some love.
As mentioned in the comments already: In your server code, you receive a message from the client using:
recvfrom(s, buf, BUFLEN, 0, (struct sockaddr *) &si_other, &slen))
The result of this function is that the message data will be written into buf and the ip address and port number of the socket that sent the message will be filled into si_other (which must be of type struct sockaddr_in).
So then, when you send a response using:
sendto(s, buf, recv_len, 0, (struct sockaddr*) &si_other, slen)
Since si_other, which you are passing as the destination address for sendto, contains the ip/port of the last message you got, the response will always go back to the sender of the last message you got. In many server applications this is a pretty common scenario: you get a request from somewhere, you send a response back to the same place.
If you want the message to go someplace else, other than the process that sent you the request, then you need to create a different struct sockaddr_in variable which contains the ip address and port of where you would like the message to go.
And in your client code, you already have the code that does that, eg (cleaned up a bit):
struct sockaddr_in si_client2;
memset((char *) &si_client2, 0, sizeof(si_client2));
si_client2.sin_family = AF_INET;
si_client2.sin_port = htons(CLIENT2_PORT);
if(inet_aton(CLIENT2_HOST, &si_client2.sin_addr) == 0)
perror("inet_aton");
So now, if you use si_client2 in your sendto(), the packet will go to that client.
Because it's UDP, delivery is not guaranteed. If there is a process listening for UDP at that ip address, on that port number, then (if no network error occurs) it will get the message. If not, nothing will happen.. your message vanishes into the void.
Keep in mind that if client 1 and client 2 are both running on the same machine, they will need to use different port numbers, because every destination (whether in a client or server role) must have a unique combination of IP and PORT.
Now, in real life applications, it is rare that a server will ever know the IP and PORT of its clients ahead of time.. usually clients will not use fixed port numbers but instead use "ephemeral ports".. port numbers which the operating system assigns at run-time. Whereas, the client will often be configured with the IP and port of the server.
So, in most cases, you would have some code in the server that keeps a list of client addresses.. perhaps a simple messaging service would keep a list of the last 100 clients it got messages from... But how this is actually done would be dictated by the needs of the application. For a simple exercise like this one, you can just hard code the addresses as I said...
The bottom line is that, to send a UDP packet to a specific destination, the sender must know the IP and PORT of that specific destination. And the only way to know that is either to have some configuration data, or for someone (such as the destination) to send a packet ahead of time letting you know of its existence. Just keep in mind that with a UDP socket you can get a message from anywhere, and you'll be given the ip/port along with the message. If you need to send a message, you need to know the ip/port of where you want to send it. It's your applications problem to figure out how it's going to get that information and where to store that information for later use.

Why server socket gives port no which is different from bound port no?

I am writing a small socket program in C. In server side I create a socket descriptor using socket() system call, then I am binding that socket with a port. After this I am trying to get the IP/Port no of the descriptor, it gives port no different then the bind port no. I am trying to get back IP/Port using getsockname() method, Is it right to use this method ? Please help me.
#define SERVER_ADDR "127.0.0.1"
#define SERVER_PORT "9090" // actual port no I am binding
#define QUEUE_LENGTH 10
int main()
{
struct addrinfo hints, *servinfo, *temp;
memset(&hints,0,sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
// here I am passing SERVER_PORT == 9090
int status = getaddrinfo(SERVER_ADDR,SERVER_PORT,&hints,&servinfo);
if(status != 0)
{
printf("Server: getaddrinfo() errored with code %d\n",status);
return;
}
int sfd = -1;
for(temp = servinfo; temp != NULL; temp = servinfo->ai_next)
{
sfd = socket(temp->ai_family,temp->ai_socktype,temp->ai_protocol);
if(sfd == -1)
{
printf("Server: Socket error with code %d\n",sfd);
continue;
}
status = bind(sfd,temp->ai_addr,temp->ai_addrlen);
if(status == -1)
{
printf("Server: Bind error with code %d\n",status);
continue;
}
printf("Server: Bind Successful\n");
// un necessary code goes here
struct sockaddr_in server_address;
char ipv4[INET_ADDRSTRLEN];
int addr_size = sizeof(server_address);
// i am using below method to get the port no from socket descriptor
getsockname(sfd, (struct sockaddr *)&server_address, &addr_size);
// I am expecting below will print 9090. but it prints different port no why ?
printf("Server Port: %d\n",server_address.sin_port);
printf("Port from getsddrinfo: %d\n",( (struct sockaddr_in *)temp->ai_addr)->sin_port);
inet_ntop(AF_INET, &(server_address.sin_addr),ipv4,INET_ADDRSTRLEN);
printf("Server IP Address: %s\n",ipv4);
// un necessary code ends here
break;
}
if(temp == NULL)
{
printf("Server: Failed to bind\n");
return;
}
status = listen(sfd,QUEUE_LENGTH);
if(status == -1)
{
printf("Server: Listening failed\n");
return;
}
printf("Server: waiting for coneections...\n");
while(1)
{
printf("Server: Main loop, will wait for client to connect...\n");
struct sockaddr client_address;
int addr_length = sizeof client_address;
// accepting client
int new_sfd = accept(sfd,&client_address,&addr_length);
}
printf("Server: Done!\n");
}
Output is:
Server: Bind Successful
Server Port: 33315 --> why this different from one I have binded (9090)
Port from getsddrinfo: 33315 --> why this different from one I have binded (9090)
Server IP Address: 127.0.0.1
Server: waiting for coneections...
Server: Main loop, will wait for client to connect...
The decimal members of struct sockaddr are returned in network byte order.
So you need to convert such values to host byte order, using the ntoh family of functions before using them, printing them.
add hints.sin_port = htons( 9090 );after hints.ai_socktype = SOCK_STREAM;

Resources