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.
Related
For a school project I have to use sockets to create a server, I think I managed to do it but I am supposed to use Telnet to test it, and whenever I try I get
telnet: connect to address 0.0.0.0: Connection refused
So i guess it is with the IP that I'm wrong.
The simplified version of my code that should still work for one connection is
int main(int argc , char *argv[])
{
int sock;
int fd = 0;
int err = 0;
struct sockaddr_in sock_data;
socklen_t addr_size;
char *path;
path = get_current_dir_name();
if (argc == 2)
printf("%s", Usage);
sock = socket(AF_INET , SOCK_STREAM , 0);
if (sock == -1) {
printf("Could not create socket");
return (84);
}
memset(&sock_data, 0, sizeof(struct sockaddr_in));
sock_data.sin_family = AF_INET;
sock_data.sin_port = htons(5133);
sock_data.sin_addr.s_addr = htonl(INADDR_ANY);
printf("%s, %s, %s\n", path, sock_data.sin_addr, inet_ntoa(sock_data.sin_addr));
if (bind(sock, (const struct sockaddr *) &sock_data, sizeof(sock_data)) == -1)
printf("Error with binding\n");
if (listen(sock, LISTEN_BACKLOG) == -1)
printf("Error with listen");
addr_size = sizeof(struct sockaddr_in);
err = accept(sock, (struct sockaddr *) &sock_data, &addr_size);
while ((sock = accept(sock, NULL, NULL)) < 0)
err = 0;
return 84;
}
I saw this link: TCP sockets in c
that was quite clear but I still don't get how I am supposed to test my program
And the more I work on it the more I am convinced that I must have made a stupid mistake.
So do you know where I went wrong?
In your Telnet command you missed a port. The commamd should be like a
telnet system_ip port
For example
telnet 192.168.1.1 5631
I am currently coding a small chat application in C for learning network.
I develop using the Transmission Control Protocol with socket in C. I was able to connect to my server with a client not coded by myself (on local network). Now telnet succeed to connect to my chat server(so with server and telnet client on the same computer) and I can send and receive message BUT my very simple client cannot connect to it.
Since the begining I use port 9002 and right now I am trying to connect with IPv6 address ::1.
Here the "accept client" code of my server:
int main(void)
{
//Create the socket
int sock = socket(AF_INET6, SOCK_STREAM, 0);
printf("Socket créer\n");
//Set up the socket interface
struct sockaddr_in6 sin6 = { 0 };
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(PORT);
sin6.sin6_addr = in6addr_any;
//Bind the socket on the port
if(bind(sock, (struct sockaddr *) &sin6, sizeof(struct sockaddr_in6)) == SO_ERROR)
{
perror("bind()");
errx(EXIT_FAILURE, "Fail to bind");
}
//Make the sockey listen the port
if(listen(sock, MAX_CLIENT) == SO_ERROR)
{
perror("listen()");
errx(EXIT_FAILURE, "Fail to listen");
}
printf("Socket listening\n");
int csock;
size_t clientID = 0;
--snip--
while(1)
{
struct sockaddr_in6 csin6;
memset(&csin6, 0, sizeof(struct sockaddr_in6));
int sin6size = sizeof(struct sockaddr_in6);
//Accept a communication
printf("Wait for communication\n");
csock = accept(sock, (struct sockaddr *) &csin6, &sin6size);
printf("Connection accepted\n");
char msg[16];
sprintf(msg, "CONNECTED - %zu\n", clientID);
send(csock, msg, sizeof(msg), 0);
printf("Client %zu connected\n", clientID);
//Handle client
--snip--
}
So this is a basic connection with socket using connected communication. The server handle several client in the while loop thanks to threading.
Here the code of the client:
void *sender(void *arg)
{
int socket = (int)(long)arg;
char buffer[BUFF_SIZE];
while(1)
{
scanf("%s", buffer);
send(socket, buffer, strlen(buffer), 0);
bzero(buffer, BUFF_SIZE);
}
}
int main(int argc, char *argv[])
{
if(argc < 2)
errx(EXIT_FAILURE, "Usage: ./client <server ip>\n");
//Create the socket
int sock = socket(AF_INET6, SOCK_STREAM, 0);
struct hostent *hostinfo = NULL;
hostinfo = gethostbyname2(argv[1], AF_INET6);
if(hostinfo == NULL)
errx(EXIT_FAILURE, "Can't connect to the server\n");
//Set up the socket interface
struct sockaddr_in6 sin6 = { 0 };
sin6.sin6_family = AF_INET6;
sin6.sin6_port = htons(PORT);
sin6.sin6_addr = *(struct in6_addr *)hostinfo->h_addr;
if(connect(sock, (struct sockaddr *) &sin6, sizeof(struct sockaddr)) == SO_ERROR)
{
perror("connect()");
errx(EXIT_FAILURE, "Fail to connect");
}
printf("Connection established\n");
pthread_t sending;
if(pthread_create(&sending, NULL, sender, (void *)(long)sock) != 0)
printf("Fail to create a thread\n");
//Handle reception
char buffer[BUFF_SIZE];
int n;
while((n = recv(sock, buffer, BUFF_SIZE - 1, 0)) >= 0)
{
buffer[n] = '\0';
printf("%s", buffer);
}
printf("Erreur: %d\nConnection broken\n", n);
pthread_cancel(sending);
close(sock);
return EXIT_SUCCESS;
}
So I start the client with:
~ ./client ::1
The output is the following:
Connection established
Error: -1
Connection broken
While the server is still "Waiting for communication". This means that the server do not accept the connection but the client succeed to connect.
Thank you for you help.
It is probably already the connect(), which fails here:
if(connect(sock, (struct sockaddr *) &sin6, sizeof(struct sockaddr)) == SO_ERROR)
SO_ERROR is not meant to be used here, but as a socket option when retrieving the error when an asynchronous connect fails. A (synchronous) connect() returns -1 on error and sets errno, so do
if(connect(sock, (struct sockaddr *) &sin6, sizeof(struct sockaddr)) == -1) {
...
Later, the recv here:
while((n = recv(sock, buffer, BUFF_SIZE - 1, 0)) >= 0)
fails with errno ENOTCONN, since the connection failed beforehand.
The same SO_ERROR mistake is present at various locations in your server code; it is possible, that already the bind() there fails! The call to listen() will then autobind it to a free ephemereal port, so the call as well as the call to accept() will succeed.
Why can the call to bind() fail? You might have to set the socket option SO_REUSEADDR when (re-)starting the server, otherwise it might refuse to use a recently bound port if connections are still in TIME_WAIT state. Place this directly before the bind() call:
int one = 1;
setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &one, sizeof(one));
This might help.
I have simple TCP server program. After I close it with CTRL+C and restart again in some cases telnet client report me "connection refused". Why it happens not always, but just in some cases? Command ps shows nothing regarding my programm.
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <stdio.h>
#include<string.h>
void printHex(char *bts);
int main() {
char str[100];
int listen_fd, comm_fd;
struct sockaddr_in servaddr;
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
bzero( &servaddr, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htons(INADDR_ANY);
servaddr.sin_port = htons(22000);
printf("binding\n");
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
printf("listening\n");
listen(listen_fd, 10);
printf("accepting\n");
comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
printf("accep done\n");
int cn = 0;
while(1) {
bzero(str, 100);
printf("will read\n");
int br = read(comm_fd, str, 100);
printf("read done\n");
if (br > 0) {
printHex(str);
} else if (br <= 0) {
comm_fd = accept(listen_fd, (struct sockaddr*) NULL, NULL);
printf("accep done\n");
}
printf("error %d \n", br);
}
}
void printHex(char *bts) {
char *s = bts;
int i = 0;
do {
printf("%02X ", (unsigned char) *bts);
} while (*++bts !=0);
printf("%s\n",s);
}
You should check all return values from system calls:
int res;
res = bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
if (res == -1)
// handle error
listen_fd = socket(AF_INET, SOCK_STREAM, 0);
if (listed_fd == -1)
// handle error
Most likely you will find then that your code fails on a bind system call, which means you can't reuse socket on same IP address, protocol and port. You can change this using setsockopt call:
// allow to rebind
int reuseaddr_on = 1;
res = setsockopt(listen_fd, SOL_SOCKET, SO_REUSEADDR,
&reuseaddr_on, sizeof(reuseaddr_on));
if (res < 0)
{
stderr("Setting of SO_REUSEADDR on server's"
"socket failed");
}
You should also close a socket when you are done with it.
while(1)
{
// your loop
}
res = close(comm_fd);
if (res == -1)
// handle error
As Linux Programmer's Manual says on pages devoted to close call:
NOTES
Not checking the return value of close() is a common but nevertheless serious programming error. It is quite possible that
errors on a previous write(2) operation are first reported at the final close(). Not checking the return value when closing the file may lead to silent
loss of
data.
Always check the return values of your syscalls.
In this case,
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
fails with EADDRINUSE, because you didn't set SO_REUSEADDR on the socket before binding.
When you do CTRL-C and restart again, is the bind sucessful?
bind(listen_fd, (struct sockaddr *) &servaddr, sizeof(servaddr));
You need to check the status of the bind call. In all likelihood, this has failed due to connection having moved to TIME_WAIT state in server. And from this follows the error "connection refused" in client.
Far the bind to be successful when the server is run immediately after CTRL-C, use the SO_REUSEADDR in your socket option. With this bind will be successful, as long as there isn't another program bound to the port.
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.
I'm making a client program in C that has to deal with this situation:
1- server program receives udp datagram in port no 8080 sent by client with a port number X
2- server creates a new socket (TCP) in port number X
3- using this TCP socket, server reads a string sent by the client
(running on localhost)
I don't need to make the server program, it's already done. The points 1 and 2 are covered, but I've been a couple of days trying to work out the 3rd point and I'm not able to make it work ><
The code I've got for the client is this:
#define MYPORT 8080
int main(int argc, char *argv[ ]) {
int sockfd;
/* connector’s address information */
struct sockaddr_in their_addr;
struct hostent *he;
int numbytes;
int sockfd2, n;
struct sockaddr_in serv_addr;
struct hostent *server;
char buffer[256];
if (argc != 3) {
fprintf(stderr, "Usage: %s <hostname> <message>\n", argv[0]);
exit(1);
}
/* get the host info */
if ((he = gethostbyname(argv[1])) == NULL) {
perror("Error obtaining the client. \n");
exit(1);
}
else printf("Client obtained\n");
if((sockfd = socket(AF_INET, SOCK_DGRAM, 0)) == -1) {
perror("Error creating UDP socket\n");
exit(1);
}
else printf("UDP Socket done\n");
their_addr.sin_family = AF_INET;
printf("Port: 8080\n");
their_addr.sin_port = htons(MYPORT);
their_addr.sin_addr = *((struct in_addr *)he->h_addr);
memset(&(their_addr.sin_zero), '\0', 8);
sockfd2 = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd2 < 0)
error("ERROR opening socket");
server = gethostbyname(argv[1]);
if (server == NULL) {
fprintf(stderr,"ERROR, no such host\n");
exit(0);
}
//sending port where the TCP socket will be associated
//server client connects correctly to this port
//and the code it's working fine in this point
if((numbytes = sendto(sockfd, argv[2], strlen(argv[2]), 0, (struct sockaddr *)&their_addr, sizeof(struct sockaddr))) == -1)
{
perror("Client-sendto() error lol!");
exit(1);
}
//port is sent, now let's connect to the port by tcp and write the string
//not working properly from now on
bzero((char *) &serv_addr, sizeof(serv_addr));
serv_addr.sin_family = AF_INET;
bcopy((char *)server->h_addr,
(char *)&serv_addr.sin_addr.s_addr,
server->h_length);
serv_addr.sin_port = htons(atoi(argv[2]));
if (bind(sockfd2,(struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR connecting");
listen(sockfd2, 5);
accept(sockfd2, 0, 0);
printf("accepted!\n");
//sending the string to the TCP Port...
if((numbytes = sendto(sockfd2, "hi", 2, 0, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr))) == -1)
{
printf("Client-sendto()-TCP error\n");
exit(1);
}
if (close(sockfd) != 0) printf("Client-sockfd-UDP closing is failed!\n");
else printf("Client-sockfd-UDP successfully closed!\n");
if (close(sockfd) != 0) printf("Client-sockfd2-TCP closing is failed!\n");
else printf("Client-sockfd2-TCP successfully closed!\n");
return 0;
}
The code works for the first two steps, but in the last step, it seems it's not connecting well with the TCP port, because my client program ends but my server program says that he receives null.
And of course I'm always sending ports > 1024
Thanks in advance, any help will be so appreciated.
listen(sockfd2, 5);
accept(sockfd2, 0, 0);
printf("accepted!\n");
I haven't read all your code, but the above (at least) is wrong. You absolutely need to retain the return value of accept: it's the socket you need to write to!
accept returns a file descriptor for the new TCP socket that has just been created for communicating with the "server" in your case. You need to use that as the file descriptor you write your string to.
(The sendto call just after that, apart from using the wrong socket, is a bit suspicious since the server will have no way to determine how much data to read/where the message stops. Passing a length of 3 (to include the \0 byte, would be a bit less suspicious.)