The following code is a socket programming sample for a TCP client.
But when I run this, connect() is returned as Address family not supported by protocol.
I have heard, this problem will happen if the platform does not support ipv6.
But AF_INET I wrote is ipv4.
Also my server, that is CentOS6.4, is configured within an inet6 addr .
Does anyone know why?
#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
int
main(){
struct sockaddr_in server;
int sock;
char buf[32];
int n;
sock = socket(AF_INET,SOCK_STREAM,0);
perror("socket");
server.sin_family = AF_INET;
server.sin_port = htons(12345);
inet_pton(AF_INET,"127.0.0.1",&server,sizeof(server));
connect(sock,(struct sockaddr *)&server,sizeof(server));
perror("connect");
memset(buf,0,sizeof(buf));
n = read(sock,buf,sizeof(buf));
perror("read");
printf("%d,%s\n",n,buf);
close(sock);
return 0;
}
The code passes the wrong destination address and wrong number of arguments to inet_pton(). (For the latter the compiler should have warned you about, btw)
This line
inet_pton(AF_INET, "127.0.0.1", &server, sizeof(server));
should be
inet_pton(AF_INET, "127.0.0.1", &server.sin_addr);
Verbatim from man inet_pton:
int inet_pton(int af, const char *src, void *dst);
AF_INET
[...] The address is converted to
a struct in_addr and copied to dst, which must be sizeof(struct in_addr) (4) bytes (32 bits) long.
Not related to the problem, but also an issue, is that read() returns ssize_t not int.
The following lines shall be adjusted:
int n;
[...]
printf("%d, %s\n", n, buf);
to become:
ssize_t n;
[...]
printf("%zd, %s\n", n, buf);
Set the server address like this;
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = inet_addr(host);
addr.sin_port = htons(port);
I seen this error during bind. Cause was of using localhost instead of IP:
./myprogram localhost:7777
*** exception! `bind' failed for `localhost:7777' (97, Address family not supported by protocol)
./myprogram 127.0.0.1:7777
OK! Listening...
In addition: this error happens on one Linux host and does not appear on another. I check and compare network settings on this machines (lo device, /etc/hosts, /etc/host.conf, etc) and not found essential difference
Related
Note: I found the solution which researching for this question. The next one making this mistake will hopefully discover this question before spending to much time on this.
I've been trying to implement a TCP server on a Linux system. The problem is that I receive a very generic error message that doesn't reveal the cause of the problem:
$ gcc -Wall -Wextra main.c
$ ./a.out
bind: Cannot assign requested address
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <unistd.h>
#include <sys/socket.h>
#include <netinet/in.h>
int main() {
int sockfd = socket(AF_INET, SOCK_STREAM, 0);
if(sockfd == -1) {
fprintf(stderr, "socket: %s\n", strerror(errno));
return EXIT_FAILURE;
}
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = 8080;
addr.sin_addr.s_addr = INADDR_LOOPBACK;
if(bind(sockfd, (const struct sockaddr*)&addr, sizeof(addr)) != 0) {
fprintf(stderr, "bind: %s\n", strerror(errno));
return EXIT_FAILURE;
}
if(close(sockfd) != 0) {
fprintf(stderr, "close: %s\n", strerror(errno));
return EXIT_FAILURE;
}
}
There are countless questions on this site that describe a similar problem, but the key thing here is that it works when I try to bind to INADDR_ANY instead of INADDR_LOOPBACK. I found a few questions that had this issue, but the other way around which is a bit weird.
What are possible causes for this error message?
I've been assigning the port and address wrong:
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = 8080;
addr.sin_addr.s_addr = INADDR_LOOPBACK;
should be
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = htons(8080);
addr.sin_addr.s_addr = htonl(INADDR_LOOPBACK);
htons stands for "host to network short" and htonl stands for "host to network long", and are refering to the byte order in which the address and port are encoded.
INADDR_ANY is the address 0.0.0.0, the byte order doesn't matter here. INADDR_LOOPBACK is the address 127.0.0.1 which was incorrectly understood as 1.0.0.127.
I am hoping that this is a relatively simple answer to my question. I am attempting to learn how to program in sockets and I just can't seem to get a basic UDP example working. I am attempting to just send a string "hello" from one computer to another read it on the screen.
I started with this website
https://www.programminglogic.com/sockets-programming-in-c-using-udp-datagrams/
then tried:
https://www.abc.se/~m6695/udp.html
I have also looked at
https://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html
but it seems that each time I try to code nothing happens. I get no errors, I just don't get any communication. I can ping my server computer from my client computer at least
My setup:
I currently have two computers one running Ubuntu 16.04 the other 14.04.
I was hoping to start off with something easy by connecting them directly. But I have tried connecting them through a switch. No success.
On the "server" computer I set up my network card to have by opening the terminal and
sudo ifconfig enps60 192.168.1.1 netmask 255.255.255.0
To create my server code in terminal I type
gedit udp_server.c
and in the text editor I type
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>
int main()
{
int udpSocket, nBytes;
char buffer[1024];
struct sockaddr_in serverAddr, cientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
/* Create UDP socket */
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
/* Configure settings in address struct */
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(0);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.1");
memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero));
/* Bind Socket */
bind(udpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
printf("bind complete. Port number = %d\n", ntohs(serverAddr.sin_port));
addr_size = sizeof(serverStorage);
while(1)
{
nBytes = recvfrom(udpSocket, buffer, 1024, 0, (struct sockaddr *)%clientAddr, &addr_size);
printf("any bytes: %d\n, nBytes);
}
}
I then compile my code in terminal by typing
gcc -o udp_server udp_server.c
On my client computer (ubuntu 14.04) I open the terminal and type
sudo ifconfig eth0 192.168.1.2 netmask 255.255.255.0
then to create my client code in terminal I type
gedit udp_client.c
and in the text editor I type
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
int main()
{
int udpSocket, portNum, nBytes;
char buffer[1024] = "hello";
struct sockaddr_in serverAddr;
socklen_t addr_size;
unsigned int alen;
/*create UDP socket */
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
/* Configure settings in address struct */
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(0);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.1");
memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero));
addr_size = sizeof(serverAddr);
while(1)
{
printf("sending %s\n", buffer);
nBytes = strlen(buffer);
sendto(udpSocket, buffer, nBytes, 0, (struct sockaddr *)&serverAddr, addr_size);
sleep(1);
}
return 0;
}
I apologize if my code isn't that polished also.
Ok, well thanks guys for all the suggestions, but I do have some code that works.
I still am very unsure how any of this works, but for starters I was selecting an incorrect port number. According to Steve Summitt I checked my connection using Netcat, and when I would look at port 0 netcat would kindly let me know that I can't choose a port number that low. This is a bit confusing as everything I am reading says that port numbers start at 0. Also there is a thing about trying not to use well known ports which used to be 0-255 but is now 0-1023. I was trying to figure out if I know what ports I can use or not and I came across this.
https://sort.veritas.com/public/documents/vie/7.3/aix/productguides/html/sfcfsha_config/apgs04s03.htm
Although I am unsure the context is only when using IPv6 protocol?
Also I found this list.
https://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml
I guess there are a bunch of applications on every machine that uses these ports?
The quick solution: I set the port to 1024 and forgot to bind my client socket to my client computers network card. I also changed the way I do memset (I thought I understood it, but I might not)
for the complete solution:
Current Setup:
I have two Ubuntu machines connected together by a simple switch. The machines are what I am calling a server (ubuntu 16.04) and a client (ubuntu 14.04).
The first step I did is assign static IPs to each machine (I think this is only recommended for my server computer, but I didn't know how to get my DHCP address of my client in c).
in my server computer I opened my terminal (ctrl + alt + t)
sudo ifconfig enp6s0 192.168.1.1 netmask 255.255.255.0
in the client computer I opened my terminal and typed
sudo ifconfig eth0 192.168.1.2 netmask 255.255.255.0
now going back to the server computer in terminal I typed
gedit udp_server.c
which opened up a text editor
/************** UDP Server Code *****************/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <ctype.h>
int main()
{
int udpSocket, nBytes;
char buffer[5];
struct sockaddr_in serverAddr, clientAddr;
struct sockaddr_storage serverStorage;
socklen_t addr_size, client_addr_size;
int i;
/* Create UDP socket */
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
/* Configure settings in address struct */
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(1024);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
memset(serverAddr.sin_zero, '\0', sizeof(serverAddr.sin_zero);
/* Bind socket with address struct */
bind(udpSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr));
printf("bind complete port number %d\n", ntohs(serverAddr.sin_port));
/* Initialize size variable to be used later on */
addr_size = sizeof(serverStorage);
while(1)
{
nBytes = recvfrom(udpSocket, buffer, 5, (struct sockaddr *)&clientAddr, &addr_size);
printf("any bytes %d\n", nBytes);
}
return 0;
}
now for the client code I typed (on my client computer)
gedit udp_client.c
which opened up a text editor
/************ UDP client code **********/
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <stdlib.h>
int main()
{
int udpSocket, portNum, nBytes;
char buffer[1024] = "hello";
struct sockaddr_in serverAddr, clientAddr;
socklen_t addr_size;
unsigned int alen;
/* Create UDP socket */
udpSocket = socket(AF_INET, SOCK_DGRAM, 0);
/* Configure client settings in address struct */
memset((char *)&clientAddr, 0, sizeof(clientAddr));
clientAddr.sin_family = AF_INET;
clientAddr.sin_addr.s_addr = inet_addr("192.168.1.2");
clientAddr.sin_port = htons(0);
if(bind(udpSocket, (struct sockaddr *)&clientAddr, sizeof(clientAddr)) < 0)
{
perror("bind failed");
return 0;
}
printf("client bound");
/* configure server settings in struct */
memset((char *)&serverAddr, '0', sizeof(serverAddr));
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(1024);
serverAddr.sin_addr.s_addr = inet_addr("192.168.1.1");
printf("the socket ip addr is: %s\n", inet_ntoa(clientAddr.sin_addr));
addr_size = sizeof(serverAddr);
while(1)
{
sleep(2);
nBytes = strlen(buffer);
if(sendto(udpSocket, buffer, nBytes, 0, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) == -1)
{
perror("send to");
exit(1);
}
printf("sent %s\n", buffer);
}
return 0;
}
some extra notes
I actually don't know if I need to bind my sockets on my client side? I bound it to port 0 and everything worked peachey. I am thinking might run into issues if I try to receive from the server?
I am still working on a metaphor for how to think about ports
I am going with that the IP address is the network card address (city) and the port number is the address within that city (task, application). Like many people can reside in a city, many tasks or programs can reside on a machine and each one might want to communicate to the world.
This is only the most basic information (I don't cover other things like connect(), send(), write(), sendmsg() as I don't know how to use them)
hopefully this post makes it easier on the next guy.
I'm writing a basic Client/Server program in C, using UDP. The idea of the program is that the client sends a message to the server, the server receives it, then echoes it back to the client (the goal being to measure RTT for UDP). Unfortunately, on the server side, when the program attempts to call sendto() to echo the message, I receive the error "Can't assign requested address".
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <strings.h>
#include <unistd.h>
#include <fcntl.h>
#define SERVER_PORT 7000
#define MAX_PENDING 10
#define MAX_LINE 1024000
int main()
{
struct sockaddr_in sin, sout;
socklen_t soutLen;
char buf[MAX_LINE];
int len;
int msgLen;
int s;
char *msg;
if( (s = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) < 0){
perror("could not establish UDP socket");
exit(1);
}
/* build address data structure */
bzero((char *)& sin, sizeof( sin));
sin.sin_family = AF_INET;
sin.sin_addr.s_addr = INADDR_ANY;
sin.sin_port = htons(SERVER_PORT);
if( (bind(s, (struct sockaddr *)&sin, sizeof(sin))) < 0){
perror("udpServer: bind");
exit( 1);
}
while(1){
if((msgLen = recvfrom(s, buf, sizeof(buf), 0,(struct sockaddr *)&sout, &soutLen))<0){
perror("udpServer: recvfrom()");
exit( 1);
}
if( (sendto(s, buf, msgLen, 0, (struct sockaddr *)&sout, sizeof(sout)))<0 ){
perror("udpServer: sendto()");
exit( 1);
}
free(msg);
}
}
Thanks in advance: I'm pretty new to C, so any advice is much appreciated!
The problem is that your sout you pass to sendto is not correct, because you are not correctly setting it's size when passing it to recvfrom:
man recvfrom:
ssize_t
recvfrom(int socket, void *restrict buffer, size_t length,
int flags, struct sockaddr *restrict address,
socklen_t *restrict address_len);
If address is not a null pointer and the socket is not connection-oriented, the source address of the message is filled in. The address_len argument is a
value-result argument, initialized to the size of the buffer associated with address, and modified on return to indicate the actual size of the address
stored there.
When you pass &sout to recvfrom, you also have to tell recvfrom the size of the structure you're passing in so it knows how much data it can write there -- soutLen is both an in parameter and an out parameter. Since you are not initializing soutLen, it probably has some value smaller than the actual size of the structure, which means that what you end up with in sout is not valid.
So you need to initialize soutLen:
struct sockaddr_in sin, sout;
socklen_t soutLen = sizeof(sout);
You should then pass this value as the size to sendto instead of sizeouf(sout) (this may not be required but it's good practice):
if( (sendto(s, buf, msgLen, 0, (struct sockaddr *)&sout, soutLen))<0 ){
Also just as a note, you are freeing msg which you never allocated. This is unrelated but might cause problems later.
Hope this helps.
I write a little socket programm that only bind to specified ip:port, but bind() failed if the struct sockaddr_in is not bzero and gcc is with option -O2.
Here is the codes:
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <arpa/inet.h>
#include <netinet/tcp.h>
int main(int argc, char **argv){
struct sockaddr_in addr;
//bzero(&addr, sizeof(addr));
addr.sin_family = AF_INET;
addr.sin_port = htons((unsigned short)9009);
inet_pton(AF_INET, "127.0.0.1", &addr.sin_addr);
int sock;
if((sock = socket(AF_INET, SOCK_STREAM, 0)) == -1){
perror("socket error");
exit(0);
}
if(bind(sock, (struct sockaddr *)&addr, sizeof(addr)) == -1){
printf("socket error: %d, %s\n", errno, strerror(errno));
exit(0);
}
return 0;
}
Please notice bzero(&addr, sizeof(addr)); is commented out, I intend to initial the sockadd_in by each member. Compile and run:
$ gcc a.c; ./a.out
OK
$ gcc -O2 a.c; ./a.out
socket error: 49, Can't assign requested address
We can know the struct sockadd_in is defined as:
struct in_addr {
in_addr_t s_addr; /* 32-bit IPv4 address */
/* network byte ordered */
};
struct sockaddr_in {
uint8_t sin_len; /* length of structure (16) */
sa_family_t sin_family; /* AF_INET */
in_port_t sin_port; /* 16-bit TCP or UDP port number */
/* network byte ordered */
struct in_addr sin_addr; /* 32-bit IPv4 address */
/* network byte ordered */
char sin_zero[8]; /* unused */
};
My question is, does the bind() implementation depends on sockaddr_in.sin_zero being cleared?
Edit: Mac OS X, Darwin Kernel Version 12.4.0 X86_64
The rules used in name binding vary between address families. and there's also this sin_zero field in struct sockaddr_in which some people claim must be set to zero. Other people don't claim anything about it (the Linux documentation doesn't even mention it at all), and there are other documentation which claim sin_zero has been removed from struct sockaddr_in,
I have tried with both bzero commented and un-commented. The commented works good some time in a local network but un-commented version works all time either local network or not. so i guess bzeroing is good practice.
im making a simple TCP client-server in c and im trying to send a message from the client to the server, but im having some problems with it.
The server does send the message (integer value > 0) but the client is unable to receive it (integer value > 0)
here is the code:
Client
#include <unistd.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <stdio.h>
int main()
{
int s_id;
char *msg = "hello";
struct sockaddr_in serv_addr;
s_id = socket (AF_INET, SOCK_STREAM, 0);
serv_addr.sin_family = AF_INET;
serv_addr.sin_port = htons (1156);
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
connect(s_id,(struct sockaddr *) &serv_addr, sizeof (struct sockaddr));
int r = recv (s_id, (char *) msg, 9, 0);
printf("%d \n", r );
printf("%s \n", msg );
return 0;
}
Server:
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
int main()
{
int s_id;
char *msg = "connected";
struct sockaddr_in my_addr, remote_addr;
s_id = socket (PF_INET,SOCK_STREAM,0);
my_addr.sin_family = AF_INET;
my_addr.sin_port = htons(1156);
my_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
bind(s_id,(struct sockaddr *) &my_addr, sizeof(struct sockaddr));
listen (s_id,5);
int size = sizeof (struct sockaddr_in);
int new_sd = accept (s_id, (struct sockaddr *) &remote_addr, &size);
int s= send(new_sd, (void *)msg, 9, 0);
printf("%d \n", s );
return 0;
}
The outputs i get (after first starting the server, and then the client) are
server side: 9
client-side: -1
hello
I am using Ubuntu 11.04 and the gcc compiler.
I hope someone out there can help.
Thank you
Umar
char *msg = "hello";
This is a string literal. It's a constant, and you can't change it.
int r = recv (s_id, (char *) msg, 9, 0);
And there you're trying to write to it.
Change your declaration to:
char msg[20];
memset(msg, 0, sizeof(msg));
If you make that change, your code works as expected.
In C you're going to have to allocate and manage buffers - there's no free lunch :)
Also take note of the other answer from Nikolai N Fetissov - you really should be checking return codes from all the system calls.
You never check for errors after any of the system calls. All of socket(2), connect(2), etc. return -1 on failure, then you can print the error description with, say, perror(3) function. Each system call manual page lists possible errors.
Edit 0:
The real problem is probably what Brian points out - you are trying to receive data into read-only memory on the client. Does it die with a segfault?