Unix C socket server not accepting connections - c

Here's the deal, I'm writing a simple tcp socket server in C (with unix system calls) that I'm not able to get to accept connections.
From what I can tell, I get through the server initialization just fine, but when I try to connect to the port that I print out (see code below) it refuses as if nothing is there.
More to the point, when I netstat that port isn't even in use. I'm not throwing any errors with my current set up, I'm all dried up for ideas.
int main(){
int sock_fd;
int conn_fd;
struct sockaddr_in serv_addr;
struct sockaddr_in cli_addr;
socklen_t* serlen;
socklen_t* clilen;
clilen = malloc(sizeof(socklen_t));
serlen = malloc(sizeof(socklen_t));
*serlen = sizeof(serv_addr);
*clilen = sizeof(cli_addr);
/*=============================Create Socket=============================*/
//Create Socket
sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if(sock_fd<0){
fprintf(stderr,"error creating socket\n");
exit(1);}
//Initialize Server Address Struct
bzero((char *) &serv_addr, *serlen);
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = 0;
/*=============================Bind Address==============================*/
//Bind socket to an address
if(bind(sock_fd,(struct sockaddr*)&serv_addr,*serlen)<0){
fprintf(stderr,"error binding\n");
exit(1);}
//Get socket data
if(getsockname(sock_fd,(struct sockaddr*)&serv_addr, serlen)<0){
fprintf(stderr,"error with socket name");
exit(1);}
/*=============================Server Started============================*/
//Listen for connections
listen(sock_fd,32);
//Print port
printf("%i", serv_addr.sin_port);
conn_fd = accept(sock_fd,(struct sockaddr*)&cli_addr,clilen);
/**Do something exciting with my new connection**/
}

Are you really trying to listen on port zero? Try a high port number, preferably > 1024. /etc/services will give a hint about free ports - but it only a set of comments, those port numbers are not enforced.
Edit: another hint. The port number should be in network order, so the assignment should use htons(). It could be that the "random numbers" you are getting are simple numbers that appear garbled because you might be on a little-endian machine (like Intel). When you print them, convert them back using ntohs().

props to #askmish for inspiring this one
//Print port
printf("%i", serv_addr.sin_port);
becomes
//Print port
printf("%i", htons(serv_addr.sin_port));

In your code:
Instead of:
serv_addr.sin_port = 0;
try this:
serv_addr.sin_port=htons(2056);//Any port no.
Instead of:
listen(sock_fd,32);
try this:
if(listen(sock_fd,SOMAXCONN)<0)//Just to be sure that you are considering max. no. of requests
{ fprintf(stderr,"error with listen");
exit(1);}
Also for:
conn_fd = accept(sock_fd,(struct sockaddr*)&cli_addr,clilen);
Add this:
if(conn_fd <0)
{
//handle the error here
}
If none of these solve your issues, then, there might be problem with the client code or your server environment.

Related

Connecting to local virtual machine

I suspect this has an easy solution I'm overlooking, probably to do with the client or how this is set up.
Anyways, I'm trying to set up a simple Echo server/client to understand the basics of socket programming. I have a virtual machine running Linux Mint, and the host is running Windows 10. The virtual machine I am setting to run the server c code, and the Windows will be running the client.
I started off making the server code
//Echo Server for UNIX: Using socket programming in C, a client sends a string
//to this server, and the server responds with the same string sent back to the client
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
int main()
{
char stringBuffer[50]; //string buffer for reading incoming and resending
int listener, communicator, c; //store values returned by socket system call
if((listener = socket(AF_INET, SOCK_STREAM, 0)) == -1) //creates a new socket
puts("Could not create socket");
puts("Socket Created");
struct sockaddr_in servAddr, client; //structure from <netinet/in.h> for address of server
servAddr.sin_family = AF_INET; //addressing scheme set to IP
servAddr.sin_port = htons(8888); //server listens to port 5000
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //symbolic constant of server IP address
//binds the socket to the address of the current host and port# the server will run on
if (bind(listener, (struct sockaddr *) &servAddr, sizeof(servAddr)) < 0){
puts("Bind failed");
return 1;
}
puts("Bind Successful");
listen(listener, 5); //listens for up to 5 connections at a time
c = sizeof(struct sockaddr_in);
if ((communicator = accept(listener, (struct sockaddr*)&client, (socklen_t*)&c ))<0)
puts("accept failed");
puts("Connection Accepted");
//wait until someone wants to connect, then whatever is sent can be read from communicator, which can then be sent back
while(1){
bzero(stringBuffer, 50); //sets buffer to 0
read(communicator, stringBuffer, 50); //reads from communicator into buffer
write(communicator, stringBuffer, strlen(stringBuffer)+1); //returns back
}
return 0;
}
after that I tested it out by opening another terminal in the guest machine and typed "telnet localhost 8888" and input whatever strings I wanted.
This test worked so now, onto my Windows machine to create the client side of the socket programming:
#include <winsock.h>
#include <stdio.h>
#include <string.h>
#pragma comment(lib,"ws2_32.lib") //Winsock Library
int main(int argc, char *argv[])
{
WSADATA wsadata; //variable for using sockets in windows
SOCKET sock; //socket variable for network commands
char sendString[50], recieveString[50]; //variables for sending and recieving messages to/from server
//check if WSA initialises correctly
if (WSAStartup(MAKEWORD(2,2), &wsadata) != 0)
printf("Error Code: %d", WSAGetLastError());
//creates new socket and saves into sock
if ((sock = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET)
printf("Could not create socket: %d", WSAGetLastError());
printf("Socket created\n");
struct sockaddr_in servAddr;
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //sets the IP address to the same machine as the server
servAddr.sin_family = AF_INET; //addressing scheme set to TCP/IP
servAddr.sin_port = htons(8888); //server address is on port 8888
//connects to device with specifications from servAddr
if (connect(sock, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0) {
printf("Connection Error %d\n", WSAGetLastError());
return 1;
}
printf("Connection Accepted\n");
while(1){
fgets(sendString, 50, stdin); //uses stdin to get input to put into sendString
//sends sendString to server using sock's properties
if (send(sock, sendString, strlen(sendString) + 1, 0) < 0); {
printf("Send Failed");
return 0;
}
//reads from server into recieveString
if ((recv(sock, recieveString, 50, 0)) == SOCKET_ERROR)
printf("Recieve Failed");
printf("%s", recieveString); //prints out recieveString
}
}
Now, with the server still running, when I try out the client-side, I get the response "Connection Error" (from line 35). Having looked at both Unix and WinSock examples, I'm unsure as to why I would be failing the connection. I suspect it might have something to do with a windows to linux VM but I'm not sure.
---UPDATE---
Having updated the accidental semicolon and added the WSAGetLastError, it's showing an error code of 10061; This translates to
"Connection refused.
No connection could be made because the target computer actively refused it. This usually results from trying to connect to a service that is inactive on the foreign host—that is, one with no server application running."
[after the 3rd edit:]
Sry, just re-read your question. The important thing is here:
The virtual machine I am setting to run the server c code, and the Windows will be running the client.
127.0.0.1 is an address always only local to an IP enabled box. So you your server is listening on the interface 127.0.0.1 local to the Linux VM and the client tries to connect to 127.0.0.0 local to the Windows box. Those two interfaces are not the same. The result is the obvious, namely the client does not find anything to connect to.
127.0.0.1 (the so called "IPv4 local loopback interface") can only be used for connections local to exactly one box.
if (connect(sock, (struct sockaddr *)&servAddr, sizeof(servAddr)) < 0); {
printf("Connection Error");
return 1;
}
This is just a trivial syntax mistake. You are entering the block unconditionally. Remove the first semicolon.
However there is a much more important point to be made. When you get an error from a system call such as connect(), you must print the error. Not just some message of your own devising. Otherwise you don't know whether you simply have a bug, or a temporary problem, or a long-lasting problem, or a permanent problem.
Change the printf() to:
printf("Connect error %s\n", WSAGetLastError());
and then don't continue as though the error didn't happen.
Note that this applies to all system calls, specifically including socket(), bind(), listen(), connect(), accept(), recv(), send(), and friends.

Socket connection from compiled c.cgi

On linux I want to connect to a demon, via a socket in a compiled c.cgi program (cgic), which is listening for incoming socket connections. I know the server works because it will responded to 'nc' commands. Assume the server is black-boxed, I can't change it. In my client program I have:
int sockfd;
int len;
struct sockaddr_in address;
int result;
char ch[] = "get=DeviceNo";
sockfd = socket(AF_INET, SOCK_STREAM, 0);
address.sin_family = AF_INET;
address.sin_addr.s_addr = inet_addr("127.0.0.1");
address.sin_port = 3042;
len = sizeof(address);
result = connect(sockfd, (struct sockaddr *) &address, len);
Which returns with a "Connection Refused" error at this point. As a test I compiled the netcat into the .cgi program which does work:
system("echo '-r get=DeviceNo' | nc localhost 3042");
Am I missing something maybe how the socket class is handled within a .cgi? What should I do to try and get this socket to connect or what can I do to further troubleshoot my problem?
When working with sockaddr_in type, you need to know that both socket address sin_addr.s_addr and port sin_port must be in network byte order. Most likely your host is little-endian.
So you need to use inet_addr returns correct value, but for the socket address you need to use:
address.sin_port = htons(3042);

How to re bind a udp socket in Linux

I am an experienced Linux socket programmer and am writing a server application which has many outgoing interfaces. Now server socket binds to a random source port in the start of the process along with INADDR_ANY.
Later at some point when submitting response to a specific node, i need to assign a fixed source ip address. The standard way to do this is calling bind. However, bind is called once for the port number, successive calls fail with invalid argument error.
Creating a new socket is not really a good choice since i will have to be doing this very often upon responding to some clients.
I have also explored SO and a lot of socket options such as IP_FREEBIND, but it doesn't quite suite my scenario.
Perhaps using IP_PKT_INFO and setting source address might work unless it suffers the same problem i.e. not allowing a socket once bound to INADDRANY to rebind to a fixed source ip latter.
Is there a way to unbind an existing socket or an alternate way to setting source ip address in outgoing packet?
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
printf("Failed creating socket\n");
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(1500);
addr.sin_addr.s_addr = INADDR_ANY;
// first bind succeeds
if ( (status = bind(sock, (struct sockaddr *) &addr, sizeof(addr))) < 0)
printf("bind error with port %s\n", strerror(errno));
struct sockaddr_in src_addr;
memset(&src_addr, 0, sizeof(struct sockaddr_in));
src_addr.sin_family = AF_INET;
if (inet_aton("10.0.2.17", &(src_addr.sin_addr)) == 0)
printf("Failed copying address\n");
// second bind fails
if((status = bind(sock, (struct sockaddr *)&src_addr, sizeof(src_addr))) < 0)
printf("re bind error with ip %s\n", strerror(errno));
Any ideas in this regard will be highly appreciated. I have gone through considerable material on sockets, SO etc. but no success yet.
I finally found the solution myself so accepting my own answer (shameless but correct plugin), supplemented with code sample.
I originally wanted to rewrite source address of an outgoing packet without creating the socket again where the socket was already bound. Calling bind multiple times fail for this case, and (in my particular situation), i was not able to just have separate sockets for each source ip and use it.
I found some references in IP_PACKET_INFO but it was a pain to get it to work correctly. Following reference was helpful.
Setting source of udp socket
Sample Code
Here is a trivial application which creates a udp socket, binds it to a local port, then before sending a particular message, it appends the outgoing source ip address. Keeping in mind that in my case, i created a sudo interface and assigned it another ip. The send call will fail if this is not the case.
int status=-1;
int sock = socket(AF_INET, SOCK_DGRAM, 0);
if(sock < 0)
printf("Failed creating socket\n");
int opt = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt));
struct sockaddr_in bind_addr;
memset(&bind_addr, 0, sizeof(struct sockaddr_in));
bind_addr.sin_family = AF_INET;
bind_addr.sin_port = htons(44000); // locally bound port
if((status = bind(sock, (struct sockaddr *)&bind_addr, sizeof(bind_addr))) < 0)
printf("bind error with port %s\n", strerror(errno));
// currently using addr as destination
struct sockaddr_in addr;
memset(&addr, 0, sizeof(struct sockaddr_in));
addr.sin_family = AF_INET;
addr.sin_port = htons(80); // destination port
if (inet_aton("74.125.236.35", &(addr.sin_addr)) == 0)
printf("Failed copying remote address\n");
else
printf("Success copying remote address\n");
struct sockaddr_in src_addr;
memset(&src_addr, 0, sizeof(struct sockaddr_in));
src_addr.sin_family = AF_INET;
if (inet_aton("10.0.2.17", &(src_addr.sin_addr)) == 0)
printf("Failed copying src address\n");
else
printf("Success copying src address\n");
char cmbuf[CMSG_SPACE(sizeof(struct in_pktinfo))];
char msg[10] = "hello";
int len = strlen(msg);
struct msghdr mh;
memset(&mh, 0, sizeof(mh));
struct cmsghdr *cmsg;
struct in_pktinfo *pktinfo;
struct iovec iov[1];
iov[0].iov_base = msg;
iov[0].iov_len = len;
mh.msg_name = &addr; // destination address of packet
mh.msg_namelen = sizeof(addr);
mh.msg_control = cmbuf;
mh.msg_controllen = sizeof(cmbuf);
mh.msg_flags = 0;
mh.msg_iov = iov;
mh.msg_iovlen = 1;
// after initializing msghdr & control data to
// CMSG_SPACE(sizeof(struct in_pktinfo))
cmsg = CMSG_FIRSTHDR(&mh);
cmsg->cmsg_level = IPPROTO_IP;
cmsg->cmsg_type = IP_PKTINFO;
cmsg->cmsg_len = CMSG_LEN(sizeof(struct in_pktinfo));
pktinfo = (struct in_pktinfo*) CMSG_DATA(cmsg);
//src_interface_index 0 allows choosing interface of the source ip specified
pktinfo->ipi_ifindex = 0;
pktinfo->ipi_spec_dst = src_addr.sin_addr;
int rc = sendmsg(sock, &mh, 0);
printf("Result %d\n", rc);
The key statement is
pktinfo->ipi_spec_dst = src_addr.sin_addr;
where we are specifying the source ip address to be used. The rest of things like cmsg struct etc. are merely used in order to be able to write ipoktinfo struct ourselves
There is no way to unbind and rebind an existing socket.
Why don't you create a socket for each interface instead? Since the UDP/IP protocol is connectionless, you can choose the source IP address by choosing which socket you use to send the reply with; there is no need to use the same socket the incoming datagram was received on.
The downsides are that you can no longer bind to the wildcard address, and you must use select(), poll(), multiple threads, or some other mechanism to receive datagrams from multiple sources concurrently. You'll also need some logic to efficiently pick the socket based on the client IP address.
In most cases, I suspect that adding a few route entries to route each remote IP address to the desired host IP address, and using a separate socket for each host IP address and port combination, solves the issues perfectly -- and using the very efficient kernel functionality to do so. While the behaviour may be an application requirement, I suspect it is better solved using the network interface configuration instead. Unfortunately, often the requirements are written by semi-functional idiots better suited for manual labor, and your hands are tied.. if so, I commiserate.
If you have a test network with workstations having multiple physical network interfaces, I can provide a simple example C99 test program you can use to verify the design works.

Client / Server C Connection

I am currently doing a client / server application in C that words over the internet.The server is to keep listening for new connections from the clients. Currently I am listening to cllients, but once a client connects, the server wont keep on listening for further clients. The following depicts the server side code to connect with a client:
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in sockaddr, cliaddr;
bzero(&sockaddr, sizeof(struct sockaddr_in));
bzero(&cliaddr, sizeof(struct sockaddr_in));
sockaddr.sin_family = AF_INET;
sockaddr.sin_addr.s_addr = INADDR_ANY;
sockaddr.sin_port = ntohs(atoi(argv[1]));
if(bind(sockfd, (struct sockaddr *) &sockaddr, sizeof(sockaddr)) <0) {
printf("error binding socket: %d\n", errno);
exit(1);
}
printf("binded to %d : %d\n", sockaddr.sin_addr.s_addr, htons(sockaddr.sin_port));
listen(sockfd,5);
socklen_t clilen = sizeof(cliaddr);
int newsockfd = accept(sockfd, (struct sockaddr *) &cliaddr, &clilen);
if (newsockfd < 0)
error("ERROR on accept");
printf("server connected to %d:%d\n", cliaddr.sin_addr.s_addr, htons(cliaddr.sin_port));
I am assuming i have to create some form of threads that will fork once a connection has been established. But i dont know how to implement it..
Any help is greatly appreciated
Following points might help:
You should have your accept call in a loop, so that after accepting one connection, it can go back again to accept more connections.
To process each of the connections seperately, you can create threads using pthread_create or some similar thread creation APIs.
You can choose to use Non-Blocking sockets using which you can process multiple-connections in the same thread easily.
You can collect the following Book to learn and understand how to develop concurrent server in C. It is hard to explain with examples various ways of writing concurrent server in the answer. The source codes of the examples in the book are downloadable so you can try them out even without the book (you will find in the same URL). Study the code and you will see how things work.
UNIX Network Programming, Volume 1, Second Edition: Networking APIs: Sockets and XTI
This book covers almost all the things you want to know about socket programming.

Execute two local socket servers simultaneously in C

I'm trying to simulate a DHCP server as a university task. It's required to execute at least 2 servers (or more up to 255) since several clients will be sending messages to these servers using BROADCAST (that's where the limit of 'only' 255 servers comes from).
But when I'm trying to execute 2 servers in 2 different terminals in Ubuntu, the second server executed is rejected. I guess it's due to IP at the same localhost or whatever (I'm sorry but I don't know too much about communication protocols)
How can I run several servers on the same machine? Our teacher told us about using VMWare to run another Linux OS, and try to run both, but for me this solution is far away from my thoughts... I will post the server and client connection statements, although I don't know if there's a problem with the C statements, or the OS configuration, etc.
Server:
int sockfd, newsockfd, clilen, n;
struct sockaddr_in cli_addr, serv_addr ;
char host_name[200];
int size = sizeof(struct DHCP);
char buffer[size];
struct MACIP *macip;
if ((sockfd = socket(AF_INET, SOCK_DGRAM,0)) < 0) {
printf("server: can't open datagram socket\n");
return -1;
}
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htonl(0);
serv_addr.sin_port = htons(SERV_UDP_PORT);
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) <0) {
printf("server: can't bind local address\n");
return -1;
}
Client:
int sockfd, n, clilen;
struct sockaddr_in serv_addr, cli_addr;
char serv_host_addr[30];
int size = sizeof(struct DHCP);
char buffer[size];
printf("Dirección IP del servidor (a.b.c.d) => ");
gets(serv_host_addr);
if ((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {
perror("client: can't open datagram socket");
return -1;
}
int opt=1;
if (setsockopt(sockfd, SOL_SOCKET, SO_BROADCAST,&opt, sizeof(opt))<0) {
perror("Error opcion socket");
close(sockfd);
return 1;
}
bzero((char *)&cli_addr,sizeof(cli_addr));
cli_addr.sin_family = AF_INET;
if (bind(sockfd, (struct sockaddr *) &cli_addr,sizeof(cli_addr)) < 0) {
perror("client: can't bind a port");
return -1;
}
serv_addr.sin_family = AF_INET;
inet_pton(AF_INET, serv_host_addr,&serv_addr.sin_addr);
//serv_addr.sin_addr.s_addr = inet_addr(serv_host_addr);
serv_addr.sin_port = htons(SERV_UDP_PORT);
Thank you very much in advance.
Every instance of your UDP server must listen on another port. Key line in your code is this:
serv_addr.sin_port = htons(SERV_UDP_PORT);
Looks like you have the port number as a constant (SERV_UDP_PORT). To make multiple servers run at the same time you need another port for each one.
Probably best solution in your case is to have a command line argument that would define the port on which you start your server.
Each client needs to know which port (and address of course) to connect to as well. So make your client to accept similar command line argument.
To run multiple servers, they should listen on different ports on same network interface. You may get away by using two network interfaces (say wifi and ethernet) on same network with different ips.
You might try to set up alias interfaces on an existing interface. Such alias interfaces then get their own ip address each.
Using the loopback interface (lo), which typical has 127.0.0.1 assigned, such aliases to this interface could then be called lo:0, lo:1 ... and would carry the ip addresses 127.0.0.2, 127.0.0.3, ....
For details on how to achieve this see man ifconfig.

Resources