Server on different ip's - c

I'm trying to create TCP Server that should run on a machine with multiple NIC's (eth0, eth1). Each NIC has its own IP from the network and I basically want to be able to connect to the servers running on each of the IP's at the same time. However currently I am able only to connect (netcat) to the first interface IP eth0 and when I try with eth1 I get a "Connection refused" even when I have the server only running on eth1.
I'm not sure if it is a problem with my server code (below). I bind to the required interface with setsockopt() and also use the interface IP (retrieved via ioctl), and netstat shows that the server is listening on the correct ip:port, however I am not able to connect to the one on eth1.
#include <stdio.h>
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <net/if.h>
#include <sys/ioctl.h>
#include <stdlib.h>
#include <string.h>
#define MAX_SIZE 255
struct in_addr getIfIp(char* ifName)
{
int sockfd;
struct ifreq ifr;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
ifr.ifr_addr.sa_family = AF_INET;
strncpy(ifr.ifr_name, ifName, IFNAMSIZ-1);
if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0) {
fprintf(stderr, "ioctl failed\n");
}
close(sockfd);
return ((struct sockaddr_in*)&ifr.ifr_addr)->sin_addr;
}
int startServer(char* ifName, unsigned short port)
{
int sock_descriptor, conn_desc;
struct sockaddr_in serv_addr, client_addr;
socklen_t size = sizeof(client_addr);
char buff[MAX_SIZE];
if (ifName == NULL || port == 0) {
fprintf(stderr, "invalid server parameters\n");
return -1;
}
sock_descriptor = socket(AF_INET, SOCK_STREAM, 0);
if(sock_descriptor < 0) {
fprintf(stderr, "Failed creating socket\n");
return sock_descriptor;
}
if (setsockopt(sock_descriptor, SOL_SOCKET, SO_BINDTODEVICE, ifName, strlen(ifName)) < 0) {
fprintf(stderr, "Failed setting socket option\n");
return -1;
}
bzero((char *)&serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET; // AddressFamily = Internet address
serv_addr.sin_addr = getIfIp(ifName);//INADDR_ANY;
serv_addr.sin_port = htons(port);
// bind the address to the socket file descriptor
if (bind(sock_descriptor, (struct sockaddr *)&serv_addr, sizeof(serv_addr)) < 0) {
fprintf(stderr, "Failed to bind\n");
return -1;
} else {
printf("bound to %s\n", inet_ntoa(serv_addr.sin_addr));
}
// Now start listening
if (listen(sock_descriptor, 0) < 0){
fprintf(stderr, "Listen failed");
return -1;
} else {// max queue of pending connections
printf("Listening on port %hu ...\n", port);
}
conn_desc = accept(sock_descriptor, (struct sockaddr *)&client_addr, &size);
if (conn_desc == -1) {
fprintf(stderr, "Failed accepting connection\n");
} else {
fprintf(stderr, "Connected\n");
}
close(conn_desc);
close(sock_descriptor);
return 0;
}
Any help with this would be appreciated.
[EDIT]
As mentioned in my comment, one funny thing I noticed is that once I connect to either of the interfaces I can only connect to this interface again and connect attempts to the other fail (for both eth0 and eth1) until a reboot.
Also I guess I would go ahead with INADDR_ANY for now but would really like to hear if anyone could shed some light as to why I can't connect to separate listeners (with my code here) in this case?

To have the socket listen on any interface use INADDR_ANY as listener address ...
serv_addr.sin_addr = INADDR_ANY;
and remove the call to setsockopt().
I'm not sure whether a back-log size of 0 makes sense. Also the code misses to test the outcome of the call to listen().
Finally int size should be socklen_t size.

Related

socket binding failed (address already in use, even with SO_REUSEADDR)

I am working in a simple socket project. I would like to know:
why error messages appear before telnet localhost 5678?
why SO_REUSEADDR (between socket() and bind()) don't work, and what else I should try?
Code Output Message:
bind error
Error opening file: Address already in use
telnet localhost 5678
[+]Server Socket is created.
main.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <errno.h>
#define BUFSIZE 1024 // Buffer Size
#define PORT 5678
int main() {
printf("telnet localhost 5678\n");
int rfd; // socket descriptor
int clientfd; // client descriptor
struct sockaddr_in client; // Client Socket address
socklen_t client_len; // Length of Client Data
char input[BUFSIZE]; // Client Data -> Server
int bytes_read; // Client Bytes
// 1. socket() = create a socket, SOCK_STREAM = TCP
rfd = socket(AF_INET, SOCK_STREAM, 0);
if (rfd < 0) {
fprintf(stderr, "socket error\n");
exit(-1);
}
printf("[+]Server Socket is created.\n");
// optional
int enable = 1;
if (setsockopt(rfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(int)) < 0)
fprintf(stderr, "setsockopt(SO_REUSEADDR) failed");
//Initialize the server address by the port and IP
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET; // Internet address family: v4 address
server.sin_addr.s_addr = INADDR_ANY; // Server IP address
server.sin_port = htons(PORT); // Server port
// 2. bind() = bind the socket to an address
int brt = bind(rfd, (struct sockaddr *) &server, sizeof(server));
if (brt < 0) {
int errnum;
errnum = errno;
fprintf(stderr, "bind error\n");
fprintf(stderr, "Error opening file: %s\n", strerror(errnum));
exit(-1);
}
printf("[+]Bind to port %d\n", PORT);
// 3. listen() = listen for connections
int lrt = listen(rfd, 50);
if (lrt < 0) {
printf("listen error\n");
exit(-1);
}
if (lrt == 0) {
printf("[+]Listening....\n");
}
// non-stop loop
while (1) {
// 4. accept() = accept a new connection on socket from client
clientfd = accept(rfd, (struct sockaddr *) &client, &client_len);
if (clientfd < 0) {
fprintf(stderr, "accept failed with error %d\n");
exit(-1);
}
printf("Client connected\n");
...
close(clientfd);
printf("Client disconnected\n");
}
close(rfd);
}
I'm assuming that you are using Linux. If you want to rebind to an address, you should use SO_REUSEPORT not SO_REUSEADDR. Name is really misleading. But make sure that you know how it works and whether you really want to use it or not.
You can check difference here: How do SO_REUSEADDR and SO_REUSEPORT differ?

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;
}

WinSock program in C, works only on local computer

I'm a newbie in Network Programming, started to learn how to use WinSock in C.
I don't have any knowledge in Networking right now.
Anyway, I've written the following code for Client and Server, using WinSock.
Server:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define MY_ERROR 1
#define PORT 7777
#define MAX_NUM_CLIENTS 1 /* I don't know how to thread right now. */
#define MAX_CLIENT_MSG_LEN 1000
int main()
{
WSADATA wsa;
SOCKET mySocket, acceptSocket;
struct sockaddr_in server, client;
int sockAddrInLength = sizeof(struct sockaddr_in);
char clientMessage[MAX_CLIENT_MSG_LEN];
int clientMessageLength;
char* message;
int running = 1;
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
return MY_ERROR;
}
printf("WSAStartup succeded.\n");
mySocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (mySocket == INVALID_SOCKET)
{
fprintf(stderr, "Socket creation failed.\n");
return MY_ERROR;
}
printf("Socket creation succeeded.\n");
server.sin_addr.s_addr = INADDR_ANY;
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
if (bind(mySocket, (struct sockaddr*) &server, sizeof server) == SOCKET_ERROR)
{
fprintf(stderr, "Binding socket on port %d failed.\n", PORT);
return MY_ERROR;
}
printf("Binding socket on port %d successfully.\n", PORT);
while (running)
{
listen(mySocket, MAX_NUM_CLIENTS);
printf("Waiting for a connection...\n");
acceptSocket = accept(mySocket, (struct sockaddr*) &client, &sockAddrInLength);
if (acceptSocket == INVALID_SOCKET)
{
fprintf(stderr, "Accept failed.\n");
return MY_ERROR;
}
printf("Accept succeeded.\n");
if ((clientMessageLength = recv(acceptSocket, clientMessage, sizeof clientMessage, 0)) == SOCKET_ERROR)
{
fprintf(stderr, "Recv failed.\n");
return MY_ERROR;
}
printf("Recv succeeded.\n");
printf("Data:\n");
clientMessage[clientMessageLength] = NULL; /* Null terminator */
printf("Client: %s\n", clientMessage);
message = "Hello client, I'm the server. Bye bye. :-)\n";
if (send(acceptSocket, message, strlen(message), 0) < 0)
{
fprintf(stderr, "Send failed.\n");
return MY_ERROR;
}
printf("Send succeded.\n");
}
closesocket(mySocket);
WSACleanup();
getchar();
return 0;
}
And this is the code for the Client:
#include <stdio.h>
#include <stdlib.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define IP /* My IP */
#define MY_ERROR 1
#define PORT 7777
#define MAX_SERVER_MSG_LEN 1000
int main()
{
WSADATA wsa;
SOCKET mySocket;
struct sockaddr_in server;
char* message;
char serverMessage[MAX_SERVER_MSG_LEN];
int serverMessageLength;
if(WSAStartup(MAKEWORD(2,2), &wsa) != 0)
{
fprintf(stderr, "WSAStartup failed.\n");
getchar();
return MY_ERROR;
}
printf("WSASucceeded.\n");
mySocket = socket(AF_INET,SOCK_STREAM, IPPROTO_TCP);
if (mySocket == INVALID_SOCKET)
{
fprintf(stderr, "Socket creation failed.\n");
getchar();
return MY_ERROR;
}
server.sin_addr.s_addr = inet_addr(IP);
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
if (connect(mySocket, (struct sockaddr*) &server, sizeof server) < 0)
{
fprintf(stderr, "Connection failed. error: %s\n",WSAGetLastError());
getchar();
return MY_ERROR;
}
printf("Connection established.\n");
message = "Hello server, I'm the sweet client. :-)\n";
if (send(mySocket, message, strlen(message), 0) < 0)
{
fprintf(stderr, "Sending failed.\n");
return MY_ERROR;
}
printf("Sending succeeded.\n");
if ((serverMessageLength = recv(mySocket, serverMessage, sizeof serverMessage, 0)) == SOCKET_ERROR)
{
fprintf(stderr, "Recv failed.\n");
return MY_ERROR;
}
printf("Recv succeeded.\n");
printf("Data:\n");
serverMessage[serverMessageLength] = NULL;
printf("Server: %s", serverMessage);
closesocket(mySocket);
getchar();
return 0;
}
Ok.
When I run both server and client on my comupter, and define IP (in the client code) to be my internal IP (I think, becuase it is the form of 192.168.x.x) it works fine.
When I define IP to be my external IP, it doesn't work on my computer (when I run both program in my computer). The connection failes.
In addition -
When I'm trying to run the client on any other computer, it doesn't work (when IP is defined to be my internal or my external IP), the connection failes.
My questions are:
Why when I run both server & client on my computer, it works just with my internal IP?
What should I do in order that the client could be run on another computer and it will work?
I know that maybe the answer contains terms like "internal/external IPs", "routers", maybe "firewall" or "port forwarding".
Just remember I'm really a newbie in Networking and I don't have any knowledge about those terms, so please: I hope your explnations will be beginner-friendly.
I want to start learning Networking, but my first step is to understand how to use Sockets, and I have a problem in the connetction with other computers.
If you have any articles/something like that in order to give me a better understanding of the problem, it could help too.
Thank you very much! :)
This doesn't look like a coding problem, but a network configuration problem.
Let me try and rephrase what you're saying : Please correct me if I've misunderstood:-
You have an "internal" network (192.168.x.y).
You run the client on one PC on your internal network, and the server on another.
It all works so far.
But, you're also connected to the internet, via a different 'external' IP address
- When your client tries to access the server via this address, it fails. (The exact error code from WSAGetLastError is useful here, please)
At this point, it's down to how you're connected to the net. Let's assume a typical home office scenario. You have broadband, with an ADSL router/modem giving you network connectivity. Now, while the router will have an 'external' IP address, PC's on your local network typically do NOT. So, if you try connecting to the 'external' IP, you're actually trying to talk to the router.
This is where Port forwarding comes into play. You need to configure the router to forward port 7777 to the correct IP address for your server on the internal network. You'll find a screen like this on your router somewhere.
You would enter port 7777 for both 'from' and 'to', enable TCP, and specify the LAN address of your server. The router will then forward incoming connections on port 7777 to the specified server.

Need multiple connections in C socket

I have written the following code as an intermediate to connect two programs. There is a server program running and a client program on two different systems. This code is expected to act as an intermediate between these two programs.
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
//Connect with program on server side
char * serv_con(char app_data[50])
{
int sock, bytes_recieved;
char send_data[1024];
char *recv_data = malloc(1024);
struct hostent *host;
struct sockaddr_in server_addr;
host = gethostbyname("10.47.3.249");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(3128);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8);
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("Connect");
exit(1);
}
bytes_recieved=recv(sock,recv_data,1024,0);
recv_data[bytes_recieved] = '\0';
send(sock, app_data, 50, 0);
return recv_data;
//close(sock);
}
//Connect with client app
char * cli_con(char ser_data[50])
{
int sock, connected, bytes_recieved , true = 1;
char send_data [1024];
char *recv_data = malloc(1024);
struct sockaddr_in server_addr,client_addr;
int sin_size;
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Socket");
exit(1);
}
if (setsockopt(sock,SOL_SOCKET,SO_REUSEADDR,&true,sizeof(int)) == -1)
{
perror("Setsockopt");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5000);
server_addr.sin_addr.s_addr = INADDR_ANY;
bzero(&(server_addr.sin_zero),8);
if (bind(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
perror("Unable to bind1");
exit(1);
}
if (listen(sock, 5) == -1)
{
perror("Listen");
exit(1);
}
sin_size = sizeof(struct sockaddr_in);
connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size1);
printf("\n I got a connection from (%s , %d)",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
bytes_recieved = recv(connected,recv_data,1024,0);
recv_data[bytes_recieved] = '\0';
send(connected, ser_data,50, 0);
//close(sock);
}
int main()
{
char *ser_data, *app_data;
int pid = fork();
while(1)
{
if(pid == 0)
app_data = serv_con(ser_data);
else
ser_data = cli_con(app_data);
}
}
It works fine until the client side app runs. But as soon as the client side app runs, the code exit giving the error:
Unable to bind: Address already in use
I got a connection from (192.168.0.3 , 45691)
What modification should I make in the code to rectify this error? I am working on linux. Thanks in advance.
EDIT:
I have removved the comment from close(sock)and added close(connect) in the function cli_con. The code on the client side is given below:
int sock, bytes_recieved;
char send_data[1024],recv_data[1024];
struct hostent *host;
struct sockaddr_in server_addr;
host = gethostbyname("192.168.0.2");
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("Socket");
exit(1);
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(5555);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
bzero(&(server_addr.sin_zero),8);
if (connect(sock, (struct sockaddr *)&server_addr,
sizeof(struct sockaddr)) == -1)
{
perror("Connect");
exit(1);
}
while(1)
{
//necessary codes
if (connect(sock, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) == -1)
{
close(sock);
goto connct;
}
}
But now on running, the first program doesnot exit but doesnot even print
I got a connection from (192.168.0.3 , 45691)
But just keeps on running without printing ANY messages. But on the other hand, the client exits showing the error:
Connect: Connection reset by peer
What should I do now?
When a client disconnects you create a new server socket and bind it to the same port. If the server side socket was not closed the port is still in use, so bind fails.
Usually the server side of a socket program has a loop around accept to allow it process connections from many clients. This way bind and listen are called only once.
while (connected = accept(sock, (struct sockaddr *)&client_addr,&sin_size1)) {
printf("\n I got a connection from (%s , %d)",inet_ntoa(client_addr.sin_addr),ntohs(client_addr.sin_port));
bytes_recieved = recv(connected,recv_data,1024,0);
recv_data[bytes_recieved] = '\0';
send(connected, ser_data,50, 0);
close(connected);
}
It means you're trying to listen on port 5000, but there is already a program listening on that port (possibly an earlier version of your program which didn't close the port properly.) Change the port number to another value, or close any application listening on the port.
Since you're under Linux, you can use "netstat -nlp" as root to see what programs have which ports open.
One pointer for you is that, you should close both the listen socket and the socket which you obtain from the accept call.
close(connected);
close(sock);
Also, the socket takes sometime to be freed by the OS after it's usage and so, it might fail with an "Address already in use" error. You can check again properly in your code if your SO_REUSEADDR part of the code is executing properly.
Also, since you can try to add the listen socket creation code in your main function itself and pass it as an argument to cli_con function. Commonly followed mechanism is to create one listen socket and use it to accept multiple connections from client.
I hope in your original code you have proper memory allocation, initialization etc for ser_data & app_data.

Global IPv6 adrress is unable to bind on Solaris

I am trying to bring up a sample code for IPv6 server on Solaris. When i give link local address, it is working fine. But when i give global address, it is failing to bind. Please tell me, that can we use global IPv6 address on Solaris ?
This is my code ....
#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>
/* the port users will be connecting to */
#define MYPORT 9000
/* how many pending connections queue will hold */
#define BACKLOG 10
int main(int argc, char *argv[ ])
{
/* listen on sock_fd, new connection on new_fd */
int sockfd, new_fd;
/* my address information */struct sockaddr_in6 their_addr;
socklen_t sin_size;
//struct sigaction sa;
int yes = 1;
if ((sockfd = socket(AF_INET6, SOCK_STREAM, 0)) == -1)
{
perror("Server-socket() error lol!");
return 0;//exit(1);
}
else
printf("Server-socket() sockfd is OK...\n");
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1)
{
perror("Server-setsockopt() error lol!");
return 0;//exit(1);
}else
printf("Server-setsockopt is OK...\n");
/* host byte order */
my_addr.sin6_family = AF_INET6;
/* short, network byte order */
my_addr.sin6_port = htons(MYPORT);
/* automatically fill with my IP */
inet_pton(AF_INET6,"2345:1111:aaaa::500",&my_addr.sin6_addr);
//inet_pton(AF_INET6,"fe80::203:baff:fe50:cbe5",&my_addr.sin6_addr);
my_addr.sin6_scope_id=5;
/* zero the rest of the struct */
if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(my_addr)) == -1)
perror("Server-bind() error");
return 0;//exit(1);
}
else
printf("Server-bind() is OK...\n");
if(listen(sockfd, BACKLOG) == -1)
{
perror("Server-listen() error");
return 0;//exit(1);
}
printf("Server-listen() is OK...Listening...\n");
sin_size = sizeof(struct sockaddr_in6);
if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size)) == -1)
{
perror("Server-accept() error");
//continue;
}
else
printf("Server-accept() is OK...\n");
printf("Server-new socket, new_fd is OK...\n");
printf("Server: Got connection from \n");
/* this is the child process */
/* child doesn’t need the listener */
char buf[1024];
int numbytes=0;
if((numbytes = recv(new_fd, buf, 1024, 0)) == -1)
{
perror("recv()");
return 1;//exit(1);
}
else
printf("Client-The recv() is OK...\n");
buf[numbytes] = '\0';printf("Client-Received: %s", buf);
if(send(new_fd, "This is a test string from server!\n", 37, 0) == -1)
perror("Server-send() error lol!");
/* parent doesn’t need this*/
close(new_fd);
printf("Server-new socket, new_fd closed successfully...\n");
return 0;
}
Thank you ....
Is 2345:1111:aaaa::500 configured on any of your interfaces? This is required before you can bind to that address.
2345:1111:aaaa::500 is the netmask, the IP is fe80::203:baff:fe50:cbe5
I think you will need scope id (2) to bind() to work, since it´s a Link-Local IPv6 address.
Malleus
I am not sure about on the Solaris, but on Windows 7 it requires Administrator priviledges to bind a socket to a global or multicast address.
Can you run your test with elevated priviledges?
-Jesse

Resources