I'm trying to bind the server socket so I can receive and listen for incoming messages from other clients. But I can't bind, it returns error - EINVAL (Invalid Argument). I have gone through the previously asked questions related to this error and Linux manual page says 'The socket is already bound to an address, and the protocol does not support binding to a new address; or the socket has been shut down.'
Here is the problematic server code in c:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#define LISTEN_BACKLOG 5
#define handle_error(msg) \
do { perror(msg); exit(EXIT_FAILURE); } while(0)
int main(int argc, char* argv[])
{
int sockfd, cfd;
struct sockaddr_in myaddr, cl_addr;
socklen_t cl_len;
int quit = 0, reuse = 1;
if (argc < 2)
{
fprintf(stderr, "ERROR, no port provided\n");
exit(1);
}
if ((sockfd = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1)
handle_error("socket");
printf("socket created.\n");
#ifdef SO_REUSEADDR
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, (const char*)&reuse, sizeof(reuse)) < 0)
perror("setsockopt(SO_REUSEADDR) failed");
#endif
#ifdef SO_REUSEPORT
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEPORT, (const char*)&reuse, sizeof(reuse)) < 0)
perror("setsockopt(SO_REUSEPORT) failed");
#endif
memset(&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(atoi(argv[1]));
printf("portno: %d\n", atoi(argv[1]));
if (bind(sockfd, (struct sockaddr *) &myaddr, sizeof(myaddr)) < 0)
handle_error("bind");
printf("bind successful\n");
close(sockfd);
unlink((const char *) &myaddr);
return 0;
}
When I try to start the server, I get error EINVAL as shown below:
$ ./server 8032
socket created.
portno: 8032
bind: Invalid argument
Will be grateful to receive any inputs on this, thanks!
Problem is with the way you are creating socket.
if ((sockfd = socket(PF_LOCAL, SOCK_STREAM, 0)) == -1)
Here you are creating socket for PF_LOCAL rather you want to create for AF_INET family.
Related
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?
I am quite new to C & Linux and I tried to setup a TCP socket server for Data exchange with a C-Code I compiled and executed on a Ubuntu System.
From a Tutorial I copied the following code (see below, the original version didn't include exception handling) and it worked to start the server and receive data (time & date) with a client code (on the same machine for test purpose).
Then I restarted the Ubuntu machine and since then I can't start the server anymore.
I then added exception handling to the code below and it throws "unable to bind" with errorno 22, which means "invalid argument"? This doesn't make sense to me, as the same code worked before quite good.
I assumed that the "old" socket is in a time-wait state or not closed yet, but I checked all connections with "ss -all state xxx" for all different states and everything seems alright.
Also tried to use different ports and codes - same problem.
Hope anyone can help me with this problem as I don't know what else to try.
// C-Code Server
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <time.h>
int main(int argc, char *argv[])
{
int listenfd = 0, connfd = 0;
struct sockaddr_in serv_addr;
char sendBuff[1025];
time_t ticks;
//Open a socket
listenfd = socket(AF_INET, SOCK_STREAM, 0);
memset(&serv_addr, '0', sizeof(serv_addr));
memset(sendBuff, '0', sizeof(sendBuff));
if (listenfd == -1) {
printf("Error: unable to open a socket\n");
exit(1);
}
//Create an Adress
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = htons(INADDR_ANY);
serv_addr.sin_port = htons(1234);
//Macht schon benutzte Adresse mit SO_REUSEADDR nutzbar
int opt = 1;
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, (char *)&opt, sizeof(opt))<0) {
perror("setsockopt");exit(EXIT_FAILURE);
}
if(setsockopt(listenfd, SOL_SOCKET, SO_REUSEPORT, (char *)&opt, sizeof(opt))<0) {
perror("setsockopt");exit(EXIT_FAILURE);
}
bind(listenfd, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
if ((bind(listenfd, (struct sockaddr *)&serv_addr, sizeof(serv_addr))) == -1) {
printf("Error: unable to bind\n");
printf("Error code: %d\n", errno);
exit(1);
}
listen(listenfd, 10);
while(1)
{
connfd = accept(listenfd, (struct sockaddr*)NULL, NULL);
if (connfd == -1) {
printf("Error: unable to accept connections\n");
printf("Error code: %d\n", errno);
exit(1);
}
ticks = time(NULL);
snprintf(sendBuff, sizeof(sendBuff), "%.24s\r\n", ctime(&ticks));
write(connfd, sendBuff, strlen(sendBuff));
close(connfd);
sleep(1);
}
}
In linux, how can I transmit an UDP packet using 0.0.0.0 as source address.
Here is what I have tried so far.
#include <stdio.h>
#include <stdint.h>
#include <stdlib.h>
#include <net/if.h>
#include <string.h>
#include <unistd.h>
#include <assert.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>
int main(int argc, const char *argv[])
{
struct sockaddr_in dst, src;
struct ifreq ifr;
int sock, tmp;
char payload[128];
memset(payload, 0, 128);
memset(&dst, 0, sizeof(dst));
dst.sin_family = AF_INET;
dst.sin_addr.s_addr = inet_addr("255.255.255.255");
dst.sin_port = htons(67);
memset(&src,0,sizeof(src));
src.sin_family = AF_INET;
src.sin_addr.s_addr = inet_addr("0.0.0.0");
src.sin_port = htons(68);
sock = socket(AF_INET, SOCK_DGRAM, 0);
if (sock < 0)
perror("Failed to create socket");
tmp = 1;
if (setsockopt(sock, SOL_SOCKET, SO_BROADCAST, &tmp, sizeof(tmp)) < 0)
perror("SO_BROADCAST failed");
if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, &tmp, sizeof(tmp)) < 0)
perror("SO_REUSEADDR failed");
if (setsockopt(sock, IPPROTO_IP, IP_FREEBIND, &tmp, sizeof(tmp)) < 0)
perror("IP_FREEBIND failed");
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, "eth1", sizeof(ifr.ifr_name));
if (setsockopt(sock, SOL_SOCKET, SO_BINDTODEVICE, (void *)&ifr, sizeof(ifr)) < 0)
perror("SO_BINDTODEVICE failed");
if (bind(sock, (const struct sockaddr*)&src, sizeof(struct sockaddr_in)) < 0)
perror("bind failed");
if (connect(sock, (const struct sockaddr*)&dst, sizeof(struct sockaddr_in)) < 0)
perror("bind failed");
if (write(sock, payload, 128) < 0 )
perror("Write failed");
close(sock);
return 0;
}
The problem is the the source address is only set to 0.0.0.0 if no interfaces has an IPv4 address. If just one interface has an IPv4 address, this address is used as source address.
I have looked at the source code of some of the existing DHCP clients, and found that they are using RAW sockets and building the IP and UDP header manually. This is possibility, but I would like to avoid doing this manually.
You should use RAW SOCKET and construct packet with your own efforts.
As an example you can take this: https://github.com/fycth/DHCP-server-scanner/blob/master/src/dhcpd-detector.c
This is my educational project. It is small and you can look how exactly this task is solved there.
I think if it was possible to do it via UDP sockets, they would do it instead of building one manually. So I'd suppose it doesn't work at all...
I am trying to implement a tcp client and tcp server. I am able to establish the connection but when I send a message from the client, the server doesn't receive it and yes I did look at the previous posts and there were alot of similar problems. I did follow them but I am still getting the same error. The error i am getting is from server side:
recv: Socket operation on non-socket
Here is my code. If you can please let me know what I am doing wrong, I would really appreciate it. I think there is a problem in my server implementation.
Server:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 3490
#define BACKLOG 10
int main()
{
struct sockaddr_in server;
struct sockaddr_in dest;
int status,socket_fd, client_fd,num;
socklen_t size;
char buffer[10240];
memset(buffer,0,sizeof(buffer));
int yes = 1;
if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) {
fprintf(stderr, "Socket failure!!\n");
exit(1);
}
if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, &yes, sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
memset(&server, 0, sizeof(server));
memset(&dest,0,sizeof(dest));
server.sin_family = AF_INET;
server.sin_port = htons(PORT);
server.sin_addr.s_addr = INADDR_ANY;
if ((bind(socket_fd, (struct sockaddr *)&server, sizeof(struct sockaddr )))== -1) { //sizeof(struct sockaddr)
fprintf(stderr, "Binding Failure\n");
exit(1);
}
if ((listen(socket_fd, BACKLOG))== -1){
fprintf(stderr, "Listening Failure\n");
exit(1);
}
while(1) {
size = sizeof(struct sockaddr_in);
if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size)==-1)) {
//fprintf(stderr,"Accept Failure\n");
perror("accept");
exit(1);
}
printf("Server got connection from client %s\n", inet_ntoa(dest.sin_addr));
//buffer = "Hello World!! I am networking!!\n";
if ((num = recv(client_fd, buffer, 10239,0))== -1) {
//fprintf(stderr,"Error in receiving message!!\n");
perror("recv");
exit(1);
}
// num = recv(client_fd, buffer, sizeof(buffer),0);
buffer[num] = '\0';
printf("Message received: %s\n", buffer);
close(client_fd);
return 0;
//close(socket_fd);
}
}
Client:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#define PORT 3490
int main(int argc, char *argv[])
{
struct sockaddr_in server_info;
struct hostent *he;
int socket_fd,num;
char *buffer;
if (argc != 2) {
fprintf(stderr, "Usage: client hostname\n");
exit(1);
}
if ((he = gethostbyname(argv[1]))==NULL) {
fprintf(stderr, "Cannot get host name\n");
exit(1);
}
if ((socket_fd = socket(AF_INET, SOCK_STREAM, 0))== -1) {
fprintf(stderr, "Socket Failure!!\n");
exit(1);
}
memset(&server_info, 0, sizeof(server_info));
server_info.sin_family = AF_INET;
server_info.sin_port = htons(PORT);
server_info.sin_addr = *((struct in_addr *)he->h_addr);
if (connect(socket_fd, (struct sockaddr *)&server_info, sizeof(struct sockaddr))<0) {
//fprintf(stderr, "Connection Failure\n");
perror("connect");
exit(1);
}
buffer = "Hello World!! I am networking!!\n";
if ((send(socket_fd,buffer, sizeof(buffer),0))== -1) {
fprintf(stderr, "Failure Sending Message\n");
close(socket_fd);
exit(1);
}
else {
printf("Message being sent: %s\n",buffer);
}
close(socket_fd);
}
I ran the server under gdb, and discovered that client_fd is 0 after the call to accept(). This is an invalid socket fd, so I looked at that line of code and noticed that the closing parenthesis is wrong:
if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size)==-1)) {
should be:
if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size))==-1) {
Otherwise, it's doing the comparison first and then assigning the comparison to client_fd, whereas you want the assignment of the socket, followed by the comparison.
To avoid this exact kind of frustrating bug, it's generally considered best practice to not put assignments inside of 'if' statements. I would recommend instead:
client_fd = accept(...);
if (client_fd < 0) { ... }
Also, in the client, the call to send() uses "sizeof(buffer)". 'buffer' is a char*, and the sizeof a pointer is 4 (on a 32-bit system), so only 'Hell' will be sent. To send the full string, use "strlen(buffer)" instead for the amount to send.
Your first problem is misplaced parentheses.
if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size)==-1)) {
should actually be
if ((client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size))==-1) {
As you currently have it, client_fd will be assigned to the result of the equality test between the return value of accept() and -1 and thus will always be zero in case of success.
This is one reason why many programmers avoid assignments in if statements. If written like this
client_fd = accept(socket_fd, (struct sockaddr *)&dest, &size);
if (client_fd == -1) {
then the error can't occur.
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