I've just recently started playing around with sockets in C. Today I've been trying to write a server application to run on an old laptop of mine, just to experiment a bit.
I'd like for the server's services to be accessible from remote hosts and I'm confused about which IP address the server's socket should be bound to: is there an IP address that uniquely identifies my machine online or am I missing a step (or possibly many more) here?
struct sockaddr_in serverAddress;
memset(&serverAddress, 0, sizeof(serverAddress));
serverAddress.sin_family = AF_INET;
serverAddress.sin_addr.s_addr = inet_addr("127.0.0.1");
serverAddress.sin_port = htons(8080);
if(bind(serverSocketDescriptor, (struct sockaddr*) &serverAddress, sizeof(serverAddress)) < 0) {
printf("bind() failed\n");
closesocket(serverSocketDescriptor);
WSACleanup();
return EXIT_FAILURE;
}
You want to bind to INADDR_ANY, which translates to 0.0.0.0.
serverAddress.sin_addr.s_addr = INADDR_ANY;
Binding to this address means the socket is bound to all local addresses, including localhost and any external IPs the host may have.
Suggest reading: server code sequence
// int socket(int domain, int type, int protocol);
sock_t sock = socket(AF_INET, SOCK_STREAM, 0);
if( sock < 0 )
{
perror( "socket failed" );
exit( EXIT_FAILURE );
}
// if wanting to set any socket options (setsockopt())
// this is the place to do so
struct sockaddr_in server;
memset(&server, 0, sizeof(server));
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr( INADDR_ANY );
server.sin_port = htons(8080);
if( bind( sock, (struct sockaddr*) &server, sizeof(server) ) )
{
perror( "bind() failed" );
close( sock );
exit( EXIT_FAILURE );
}
if( listen(sock, 5) )
{
perror( "listen failed" );
exit( EXIT_FAILURE );
}
struct sockaddr_in client;
size_t len = sizeof( client );
while(1)
{
sock_t clientSock = accept(sock, &client, &len);
if( clientSock < 0 )
{
perror( "accept failed" );
continue;
}
// handle client connection
close( clientSock );
}
close( sock );
Note: for long term consistency, the computer running this code needs to have a 'static' IP address, not a 'dynamic' IP address.
Related
I've done a UDP socket server in C. The server works properly only if the packets are send to 127.0.0.1. I'm trying to test it with packet sender, and I want to open a socket at the address 192.168.231.54. Anyway, if I write this address in the code, I receive an error ("Cannot assign requested address"), and this error appears for each single address different from 127.0.0.1. I want to open a socket to 192.168.231.54 and I want to send packets to this address with Packet Sender.
Here is the server code:
//*********SOCKET OPENING**************
int fd;
struct sockaddr_in serveraddr, cliaddr;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror( "socket failed" );
exit(EXIT_FAILURE);
}
memset( &serveraddr, 0, sizeof(serveraddr) );
memset(&cliaddr, 0, sizeof(cliaddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons(50037);
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
if ( bind(fd, (const struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
perror( "bind failed" );
exit(EXIT_FAILURE);
}
else{
perror("socket opened");
}
//Receiving data into hex_array array
char hex_array[lenght];
int len;
len = sizeof(cliaddr);
int n = recvfrom(fd, (uint8_t *)hex_array, lenght, NULL, ( struct sockaddr *) &cliaddr, &len);
//Printing of the received data on the socket
printf("START DEBUG:\n");
printf("%s\n", hex_array);
printf("END DEBUG.\n");
The address you bind the socket to has to actually be your computer's IP address. You can't just pick a random address.
I'm trying to write a client server program using UDP, and wait-and-stop, but I haven't got to that part, I'm still trying to figure it out how the two processes (server and client) communicate, because on my client program, the user needs to enter the server name or IP address, and a port name, and then send an expression that the server should calculate. However, I dug some tutorials in the internet and after coding accordingly (or I thought so) I can't make the client communicate with the server. Below is my code, please enlighten me what I'm doing wrong, if it's the bind(), sendto(), recvfrom() or socket(), or all of them. I can't see what exactly is wrong. I know that the client-side shouldn't run on a infinite loop, but so far I want to make the programs communicate with each other, afterwards I'll polish my code. Thanks!
client-side code:
#include <stdio.h> // Default System Calls
#include <stdlib.h> // Needed for OS X
#include <string.h> // Needed for Strlen
#include <sys/socket.h> // Needed for socket creating and binding
#include <netinet/in.h> // Needed to use struct sockaddr_in
#include <time.h> // To control the timeout mechanism
#define EXPR_SIZE 1024
#define BUFLEN 512
#define TRUE 1
#define FALSE 0
#define SERVERLEN 1024
int main(int argc, char **argv){
long portNum; // Since it's possible to input a value bigger
// than 65535 we'll be using long to
// avoid overflows
char expr[EXPR_SIZE];
char server[SERVERLEN];
int fd; // file descriptor for the connected socket
int buf[512];
struct hostent *h; // information of the host
unsigned int addrLen; // address length after getting the port number
struct sockaddr_in myaddr; // address of the client
struct sockaddr_in servaddr; // server's address
unsigned int exprLen;
socklen_t slen = sizeof(servaddr);
printf("Enter server name or IP address:");
scanf("%s",server);
printf("Enter port:");
scanf("%ld",&portNum);
if ((portNum < 0) || (portNum > 65535)) {
printf("Invalid port number. Terminating.");
return 0;
}
printf("Enter expression:");
scanf("%s",expr);
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("cannot create socket");
return 0;
}
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
if(bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0){
perror("cannot bind");
return 0;
}
/*
// Discovering the port number the OS allocated
addrLen = sizeof(myaddr);
if(getsockname(fd, (struct sockaddr *)&myaddr, &addrLen) < 0){
perror("cannot getsockname");
return 0;
}
printf("local port number = %d\n", ntohs(myaddr.sin_port));
*/
memset((char*)&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_port = htonl(portNum);
exprLen = sizeof(expr);
while(TRUE){
printf("Sending message to %s port %ld\n",server, portNum);
if (sendto(fd, expr, strlen(expr), 0, (struct sockaddr *)&servaddr, slen) < 0) {
perror("cannot sendto()");
}
printf("Success\n");
}
return 0;
}
Server-side code:
#include <stdio.h> // Default System Calls
#include <stdlib.h> // Needed for OS X
#include <string.h> // Needed for Strlen
#include <sys/socket.h> // Needed for socket creating and binding
#include <netinet/in.h> // Needed to use struct sockaddr_in
#include <time.h> // To control the timeout mechanism
#define EXPR_SIZE 1024
#define BUFLEN 512
#define TRUE 1
#define SERVERLEN 1024
int main(int argc, char **argv){
struct sockaddr_in myaddr; // address of the server
struct sockaddr_in claddr; // address of the client
char buf[BUFLEN];
int fd;
long recvlen;
socklen_t clientlen;
if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0){
perror("cannot create socket");
return 0;
}
memset((char *)&myaddr, 0, sizeof(myaddr));
myaddr.sin_family = AF_INET;
myaddr.sin_addr.s_addr = htonl(INADDR_ANY);
myaddr.sin_port = htons(0);
if(bind(fd, (struct sockaddr *)&myaddr, sizeof(myaddr)) < 0){
perror("cannot bind");
return 0;
}
clientlen = sizeof(claddr);
while (TRUE) {
recvlen = recvfrom(fd, buf, BUFLEN, 0, (struct sockaddr *)&claddr, &clientlen);
if (recvlen < 0) {
perror("cannot recvfrom()");
return 0;
}
printf("Received %ld bytes\n",recvlen);
buf[recvlen] = 0;
printf("Received message: \"%s\"\n",buf);
}
return 0;
}
The server program doesn't output anything, while the client outputs until the process is interrupted:
Enter server name or IP address:127.0.0.1
Enter port:30
Enter expression:2+2
Sending message to 127.0.0.1 port 30
cannot sendto(): Can't assign requested address
I tried changing the server name to localhost, and other ports, but to no avail.
When developing networking software (especially when using the BSD socket interface), it's important to keep things as simple as possible until you've established basic communication. Then you can incrementally add functionality, while making sure that you don't break anything along the way.
On the client side, keeping things simple means
Don't call bind in the client. The OS will choose an appropriate interface and assign a random port number, so there's no need to bind the socket.
Use a hard-coded server address (e.g. 127.0.0.1). Address 127.0.0.1 (0x7f000001) is the local host address, suitable for sending packets to a server on the same machine.
Use a hard-coded port number (e.g. 50037). Ephemeral port numbers should be greater than 0xC000 hex (49152 decimal).
Use a hard-coded message, e.g. "hello".
With that in mind, here's what the client software looks like
int main( void )
{
int fd;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror("socket failed");
return 1;
}
struct sockaddr_in serveraddr;
memset( &serveraddr, 0, sizeof(serveraddr) );
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons( 50037 );
serveraddr.sin_addr.s_addr = htonl( 0x7f000001 );
for ( int i = 0; i < 4; i++ ) {
if (sendto( fd, "hello", 5, 0, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
perror( "sendto failed" );
break;
}
printf( "message sent\n" );
}
close( fd );
}
On the server side, keeping things simple means
Bind to INADDR_ANY, i.e. let the OS pick an appropriate interface.
Bind to a hard-coded port, e.g. 50037 (must be the same port the client uses).
Don't request the address information from recvfrom, i.e. pass NULL, 0 as the last two parameters.
With that in mind, here's what the server software looks like
int main( void )
{
int fd;
if ( (fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
perror( "socket failed" );
return 1;
}
struct sockaddr_in serveraddr;
memset( &serveraddr, 0, sizeof(serveraddr) );
serveraddr.sin_family = AF_INET;
serveraddr.sin_port = htons( 50037 );
serveraddr.sin_addr.s_addr = htonl( INADDR_ANY );
if ( bind(fd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0 ) {
perror( "bind failed" );
return 1;
}
char buffer[200];
for ( int i = 0; i < 4; i++ ) {
int length = recvfrom( fd, buffer, sizeof(buffer) - 1, 0, NULL, 0 );
if ( length < 0 ) {
perror( "recvfrom failed" );
break;
}
buffer[length] = '\0';
printf( "%d bytes: '%s'\n", length, buffer );
}
close( fd );
}
I'm writing a basic proxy server in C.
I want to identify the server/machine I am receiving the request from, by name or IP.
How does one do this? I'm not sure where to get the information from.
Here's my connection code:
unsigned short port = atoi(argv[1]); /* port number to listen on */
struct sockaddr_in server;
server.sin_family = PF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons( port );
/* host-to-network-short() convert to big endian */
int len = sizeof( server );
if ( bind( sock, (struct sockaddr *)&server, len ) < 0 )
{
perror( "bind() failed" );
return EXIT_FAILURE;
}
/* activate the socket as a listener */
listen( sock, 5 ); /* 5 is number of backlogged waiting client requests */
//printf( "Listener socket created and bound to port %d on fd %d\n", port, sock );
struct sockaddr_in client;
while ( 1 )
{
// printf( "Blocked on accept()\n" );
unsigned int fromlen;
int newsock = accept( sock, (struct sockaddr *)&client, &fromlen );
/* accept() blocks */
//printf( "Accepted client connection\n" );
char buffer[5000];
int n = read( newsock, buffer, 4999 );
if ( n < 1 )
{
perror("Read() failed.\n");
}
else
{
buffer[n] = '\0';
//printf( "Rcvd message from client: \n\n----\n\n%s\n\n----\n\n", buffer );
}
Here is how you retrieve IP & hostname:
struct sockaddr_in client;
[...]
int newsock = accept( sock, (struct sockaddr *)&client, &fromlen );
printf("Client accepted: %s \n", inet_ntoa(client.sin_addr));
// And the host name
struct hostent *hostName;
struct in_addr ipv4addr;
inet_pton(AF_INET, inet_ntoa(client.sin_addr), &ipv4addr);
hostName = gethostbyaddr(&ipv4addr, sizeof ipv4addr, AF_INET);
printf("Host name: %s\n", hostName->h_name);
I'm writing a basic proxy server in C for class.
I'm testing with firefox, and I've got the server successfully receiving the browser's requests.
But now I need to send them out to the internet to get the pages the browser wants, and I'm hesitant.
Here is my present code for connecting.
I'm not sure if port 8080 is correct, and I'm not sure what to put for "gethostbyname".
That's the portion I was hoping to get some advice on.
int sock = socket( PF_INET, SOCK_STREAM, 0 );
if ( sock < 0 )
{
perror( "socket() failed" );
return EXIT_FAILURE;
}
struct sockaddr_in server;
struct hostent * hp;
server.sin_family = PF_INET;
hp = gethostbyname( "localhost" );
if ( hp == NULL )
{
perror( "Unknown host" );
return EXIT_FAILURE;
}
bcopy( (char *)hp->h_addr, (char *)&server.sin_addr, hp->h_length );
int port = 8080;
server.sin_port = htons( port );
if ( connect( sock, (struct sockaddr *)&server, sizeof( server ) ) < 0 )
{
perror( "connect() failed" );
return EXIT_FAILURE;
}
That entire gethostbyname, copying around (ha - even with the overly old bcopy)... just use getaddrinfo (extensive error checking left out for brevity):
int ret = getaddrinfo("localhost", "80" /* (or 8080, whichever applies) */, NULL, &res);
if (ret == 0) {
const struct addrinfo *r;
for (r = res; r != NULL || ret != 0; r = r->ai_next)
ret = connect(fd, res->ai_addr, res->ai_addrlen);
}
freeaddrinfo(res);
I have a code in which send multicast datagrams.
A critical piece of code:
uint32_t port;
int sockfd, err_ip;
const uint32_t sizebuff = 65535 - (20 + 8);
unsigned char *buff = (unsigned char *) malloc(sizebuff);
struct sockaddr_in servaddr, cliaddr;
struct in_addr serv_in_addr;
struct ip_mreq req;
port = str2uint16(cmdsrv->ipport);
bzero(buff, (size_t)sizebuff);
bzero(&servaddr, sizeof(servaddr));
bzero(&serv_in_addr, sizeof(serv_in_addr));
err_ip = inet_aton(cmdsrv->ipaddr, &serv_in_addr);
if(( err_ip != 0 ) && ( port != 0 )) {
servaddr.sin_family = AF_INET;
servaddr.sin_addr = serv_in_addr;
servaddr.sin_port = htons(port);
memcpy(&req.imr_multiaddr,&serv_in_addr,sizeof(req.imr_multiaddr));
req.imr_interface.s_addr = INADDR_ANY;
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if( sockfd == -1 ) {
int outerror = errno;
char *retstr = "Couldn't open socket\n";
pthread_exit(retstr);
}
else {
struct in_addr ifaddr;
ifaddr.s_addr = INADDR_ANY;
int optres3 =
setsockopt( sockfd, IPPROTO_IP, IP_MULTICAST_IF, &ifaddr,
sizeof( ifaddr ));
if( optres3 == -1 ) {
int perrno = errno;
char *retstr = "Can't set IP_MULTICAST_IF for socket\n";
printf( "Error setsockopt: ERRNO = %s\n", strerror( perrno ));
printf( "%s",retstr );
pthread_exit(retstr);
}
unsigned char ttl = 32;
int optres2 =
setsockopt( sockfd, IPPROTO_IP, IP_MULTICAST_TTL, &ttl,
sizeof( ttl ));
if( optres2 == -1 ) {
int perrno = errno;
char *retstr = "Can't set IP_MULTICAST_TTL for socket\n";
printf("Error setsockopt: ERRNO = %s\n",strerror(perrno));
printf("%s",retstr);
pthread_exit(retstr);
}
int optres =
setsockopt( sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &req,
sizeof( req ));
if( optres == -1 ) {
int perrno = errno;
char *retstr = "Can't join to multicast-group\n";
printf("Error setsockopt: ERRNO = %s\n",strerror(perrno));
printf("%s",retstr);
pthread_exit(retstr);
}
// Bind port with socket
uint16_t cliport;
cliaddr.sin_family = AF_INET;
cliaddr.sin_addr.s_addr = INADDR_ANY;
if( strcmp( cmdsrv->ipport, "16011" ) == 0 ) {
cliport = str2uint16("16003");
cliaddr.sin_port = htons(cliport);
}
else if( strcmp( cmdsrv->ipport, "16012" ) == 0 ) {
cliport = str2uint16("16004");
cliaddr.sin_port = htons(cliport);
}
else {
printf("Device hasn't such port");
pthread_exit(NULL);
}
int bindres =
bind( sockfd, (struct sockaddr*)&cliaddr, sizeof( cliaddr ));
if( bindres == -1 ) {
int perrno = errno;
perror("Error in bind\n");
}
// ADD 1 BYTE
data rawdata;
rawdata.desc = 23;
printf( "SIZEOF = %d\n", sizeof( *( cmdsrv->cmd )));
memcpy( &rawdata.cmd, cmdsrv->cmd, sizeof( *( cmdsrv->cmd )));
printf( "RAWDATA: desc = %d, cmd = %d\n", rawdata.desc, rawdata.cmd );
int outerror = 0;
printf( "Send command to IP:\n addr = %s, port = %d\n",
inet_ntoa( servaddr.sin_addr ), ntohs( servaddr.sin_port ));
int size = sendto( sockfd, &rawdata, sizeof( rawdata ), 0,
(struct sockaddr*)&servaddr, sizeof( servaddr ));
if( size == -1 ) {
perror("Can't send command to socket");
}
...
Sometimes program executes successfully (at this moment I have IP - 192.168.80.122). I can capture my multicast datagram by wireshark. That's all OK.
But if I change my IP to 192.168.1.2, I get error when is called
int optres =
setsockopt( sockfd, IPPROTO_IP, IP_ADD_MEMBERSHIP, &req,
sizeof( req ));
And I can't even capture my multicast packet. Nothing is sent.
Where's bug?
If it works for one IP but not for another, maybe this can help.
What does "IP_ADD_MEMBERSHIP: No such device" mean?
It means that the tool is trying to use multicast but the network interface doesn't support it There are two likely causes:
Your machine doesn't have multicast support enabled. For example, on Linux and FreeBSD it is possible to compile a kernel which doesn't support multicast.
You don't have a route for multicast traffic. Some systems don't add this by default, and you need to run. route add -net 224.0.0.0 netmask 224.0.0.0 eth0 (or similar). If you wish to use RAT in unicast mode only, it is possible to add the multicast route on the loopback interface.
IP_ADD_MEMBERSHIP and bind() are only required for receiving multicast, use IP_MULTICAST_IF instead for effectively a "send-only membership" of a multicast group.
IP_MULTICAST_IF sets the kernel to send multicast packets for a given group on a given interface, it is effectively "send-only" as you will not be able to receive traffic on that group after setting. This varies by platform: Posix platforms generally function this way as an optimisation, whilst Win32 will perform software level routing to propagate locally generated packets.
You might not use the interface address as INADDR_ANY.
req.imr_interface.s_addr = INADDR_ANY;
check where the loopback is running using ifconfig.
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:65536 Metric:1
You need to use interface address as inet addr i.e. 127.0.0.1
Check your loopback interface address and use that address only.