Archive

Posts Tagged ‘networking’

C Socket Programming : Part 2

July 24th, 2009 Danny 1 comment
C Scocket Programming : Part 1

R.I.P. IPv4

IPv4 ( Internet Protocol Version 4 ) is the current, most used Internet Protocol, officially described in September 1981 by the IETF, providing 4,294,967,296 (232) addresses.

Address Exhaustion

The biggest problem of IPv4 is the address exhaustion. Back at 1980 when it was defined, nobody could imagine the incredible rate the internet grows. Nowdays every embedded device ( mobile phones, PDAs, palmtops ) is a part of the internet, thus more and more addresses need to be allocated.

Welcome IPv6

IPv6 was defined in December 1998 by the IETF, almost 20 years after the release of IPv4.

IPv6 is the next-generation Internet Protocol, designated as the successor of IPv4 which still dominates the biggest part of the internet…. For now :)

IPv6 addresses use an 128-bit encoding, thus providing about 3.4×1038 addresses and this is the main advantage of it, considering the IPv4 ( 32-bit encoding ) adrress exhaustion.

It also implements new features, additions and many more advantages but that’s not what we are here to cover :) You can read the wikipedia links for more information.

IPv6 and Network Programming

Since IPv6 will be the new internet protocol, and is already defined, why make our applications with only IPv4 in mind? We can develop our applications compatible with IPv6, but at the same time, backwards compatible with IPv4. Doing so, we put our little bit, to help IPv6 come faster, since one minor problem which slows down the successor is that many programs are not developed with IPv6 in mind.

C Sockets. Changes to make

Remember C Socket Programming : Part 1 ? Lets see what changes have to be made, in order to make our applications IPv6 compatible. Take a quick look at the examples provided at Part 1.

[c light="true"]char ip[MAX_IPV4_SIZE]; //max would be lets say 111.111.111.111 = 3×4 ( nums ) + 3×1 ( dots ) = 15[/c]

We used char ip[15] in order to store the remote host IP at our example server. But since IPv6 uses a 128-bit representation we need more space to store an IPv6 address. For this reason we use :

[c light="true"]char ip[INET6_ADDRSTRLEN];[/c]

INET6_ADDRSTRLEN is define as 45 in header file <netinet/in.h> which is included by <netdb.h> which we include ourselves.

struct addrinfo.ai_family = AF_UNSPEC;

Back when we used only IPv4, the ai_family was always AF_INET. For IPv6 we would use AF_INET6, but this would break backwards-compability with IPv4. So we use AF_UNSPEC to declare that either IPv4 or IPv6 might be used, and this will be decided during the program runtime.

struct sockaddr_storage;

The struct used to storage IPv4 family information is sockaddr_in, but because IPv6 addresses require more space, there is struct sockaddr_in6 for such a case. But if we want to be compatible with both protocols, there is struct sockaddr_storage, which can hold information for both protocols!

Using helper / wrapper functions

When we called inet_ntop() in our server example, to convert the network byte-order address into human-readable format, we passed straight their_addr.sin_addr, asssuming the remote address is IPv4. But this wont be the case with IPv6 hosts, so we have to use a helper function, that will return either sin_addr or sin6_addr, depending on struct sockaddr_storage.ss_family.

Examples redefined

So, considering those changes to be made, here are the examples of C Socket Programming : Part 1 should look like.

[ server_ipv6.c ]

[c]

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#define CON_NUM 10

void *get_in_addr(struct sockaddr *sa) {
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(int argc, char** argv) {
int sockfd, new_fd;
struct addrinfo hints, *servinfo;
struct sockaddr_storage their_addr;
socklen_t sin_size;
char *buff = (char*)malloc(1024);
char ip[INET6_ADDRSTRLEN];
int rc;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

if (argc != 2) {
printf("Usage : %s PORT\n", argv[0]);
return -1;
}

if ((rc = getaddrinfo(NULL, argv[1], &hints, &servinfo)) != 0) {
printf("Error at getaddrinfo() : %s\n", gai_strerror(rc));
return 1;
}

if ((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf("Error at socket() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
return 1;
}

if (bind(sockfd, servinfo->ai_addr, servinfo->ai_addrlen) == -1) {
printf("Error at bind() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}

if (listen(sockfd, CON_NUM) == -1) {
printf("Error at listen() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}
sin_size = sizeof their_addr;
while(1) {
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
printf("Error at accept() : %s\n", strerror(errno));
continue;
}
inet_ntop(their_addr.ss_family, get_in_addr((struct sockaddr*)&their_addr), ip, sizeof ip);
printf("Got connection from %s\n", ip);
int j = 1;
while (1) {
j = recv(new_fd, buff, 1024, 0);
if ( j == 0 )
break;
if ( j == -1 ) {
printf("Error at recv() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}
printf("Recieved : %s\n", buff);
}
}
freeaddrinfo(servinfo);
close(sockfd);
close(new_fd);
return 0;
}
[/c]

[ client.c ]

[c]

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char** argv) {
int status, sock, bytes_sent;
struct addrinfo hints, *servinfo;
char msg[] = "hello!!";
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

//Not correct usage, print help and exit.
if (argc != 3) {
printf("Usage : %s HOSTNAME PORT\n", argv[0]);
return -1;
}
//get info about remote host.
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) {
printf("Error during getaddrinfo() : %s\n", gai_strerror(status));
return -1;
}
//Initialize socket.
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf(" Error during socket() : %s\n", strerror(errno));
freeaddrinfo(servinfo); //free servinfo allocated space and exit.
return -1;
}
//connect to remote host.
if (connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) == -1 ) {
printf("Error during connect() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sock); //Also close the socket.
return -1;
}
if ( (bytes_sent = send(sock, msg, strlen(msg), 0)) == -1 ) {
printf("Error during send() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sock);
return -1;
}

printf("Sent %d bytes.\n", bytes_sent);
freeaddrinfo(servinfo);
close(sock);
return 0;
}

[/c]

Resources : beej.us

Incoming Part 3 : Converting all this bunch of code, into pretty C++ Class!

As always, you can subscribe via RSS or follow wedevblog on twitter for the latest development posts!

#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char** argv) {
int status, sock, bytes_sent;
struct addrinfo hints, *servinfo;
char msg[] = “hello!!”;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

//Not correct usage, print help and exit.
if (argc != 3) {
printf(“Usage : %s HOSTNAME PORT\n”, argv[0]);
return -1;
}
//get info about remote host.
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) {
printf(“Error during getaddrinfo() : %s\n”, gai_strerror(status));
return -1;
}
//Initialize socket.
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf(” Error during socket() : %s\n”, strerror(errno));
freeaddrinfo(servinfo); //free servinfo allocated space and exit.
return -1;
}
//connect to remote host.
if (connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) == -1 ) {
printf(“Error during connect() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sock); //Also close the socket.
return -1;
}
if ( (bytes_sent = send(sock, msg, strlen(msg), 0)) == -1 ) {
printf(“Error during send() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sock);
return -1;
}

printf(“Sent %d bytes.\n”, bytes_sent);
freeaddrinfo(servinfo);
close(sock);
return 0;
}#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>

int main(int argc, char** argv) {
int status, sock, bytes_sent;
struct addrinfo hints, *servinfo;
char msg[] = “hello!!”;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

//Not correct usage, print help and exit.
if (argc != 3) {
printf(“Usage : %s HOSTNAME PORT\n”, argv[0]);
return -1;
}
//get info about remote host.
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) {
printf(“Error during getaddrinfo() : %s\n”, gai_strerror(status));
return -1;
}
//Initialize socket.
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf(” Error during socket() : %s\n”, strerror(errno));
freeaddrinfo(servinfo); //free servinfo allocated space and exit.
return -1;
}
//connect to remote host.
if (connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) == -1 ) {
printf(“Error during connect() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sock); //Also close the socket.
return -1;
}
if ( (bytes_sent = send(sock, msg, strlen(msg), 0)) == -1 ) {
printf(“Error during send() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sock);
return -1;
}

printf(“Sent %d bytes.\n”, bytes_sent);
freeaddrinfo(servinfo);
close(sock);
return 0;
}

  • Share/Bookmark
Categories: dev Tags: , , , , ,

C Socket Programming : Part 1

July 23rd, 2009 Danny 1 comment
C Socket Programming Part 2

General

Since the first years i was programming, i was always keen to applications based on communication.  Socket programming allows us to communicate with other computers / programs through networking techniques. There are 2 types of socket protocol’s that are mostly used. Those are TCP ( Stream Protocol, or SOCK_STREAM ) and UDP ( Datagram Protocol, or SOCK_DGRAM )

[table id=1 /]

For the above reasons explained, TCP/IP is the protocol used vastly on the internet, from websites, to applications. So, lets take at the steps we should make, in order to send some data over TCP to a remote PC.

  1. First of all we should have all the info required about the remote system. That includes an IP address represented in a way that our program understands, weather its IPv4 or IPv6 and if it is a hostname, do a DNS Lookup to see the IP addresses it resolves to.
  2. Initiate our socket, and feed it the data we gathered from step one.
  3. ( optional ) Bind our socket to a local port,  if we are making a server application.
  4. Connect the socket to the remote system.
  5. Send any data we want.
  6. And finally if needed, receive back other data.

Lets see how we will accomplish each task.

getaddrinfo() – magical function!!

This function will help us gather all the information ( and much more ) described in step 1 for our socket to be ready for work!

the prototype is :

[c light="true"]
int getaddrinfo(const char *node,
const char *service,
const struct addrinfo *hints,
struct addrinfo **servinfo);
[/c]

Lets examine its’ parameters..

  1. char *node – a string representing the hostname or IP that we need the information of. Pretty easy eh? :)
  2. char *service – a string that can either represent a port ( eg “80″ ), or the name of a service ( eg “http” ), which are both equivalent.
  3. struct addrinfo *hints – points to an addrinfo struct which we have already filled out with various infrmation. We will get soon on that.
  4. struct addrinfo **servinfo – a pointer-to-pointer addrinfo struct, for which the function will allocate the required memory, and fill in the information we need to know about the *node.

Here is an example call to getaddrinfo() :

[c]

#include <string.h> //memset()
#include <sys/types.h> //struct definitions
#include <sys/socket.h> //getaddrinfo()
#include <netdb.h> //AI_PASSIVE definition.

int main() {
int status;
struct addrinfo hints;
struct addrinfo *servinfo;  // will point to the results

memset(&hints, 0, sizeof hints); // make sure the struct is empty
hints.ai_family = AF_UNSPEC;     // don’t care IPv4 or IPv6
hints.ai_socktype = SOCK_STREAM; // TCP stream sockets
hints.ai_flags = AI_PASSIVE;     // fill in my IP for me

if ((status = getaddrinfo("www.example.com", "80", &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo error: %s\n", gai_strerror(status));
return 1;
}
// servinfo now points to a linked list of 1 or more struct addrinfos
// … do everything until you don’t need servinfo anymore ….
freeaddrinfo(servinfo); // free the linked-list
return 0;
}
[/c]

So, now that we have the information needed about example.com, we want to create a socket, and later on, connect to it.

Gief my socket!

As you may know, or have heard, in Unix, everything is files! Well, before you say that the word “everything” is too-much, and start arguing, i mean that everything that is about I/O ( files, devices etc ) is a file descriptor. I guess you are familiar with file I/O in C. Well, guess what! It is the same with sockets! Lets take a peek at the prototype of the function which initiates a socket.

[c light="true"]int socket(int domain, int type, int protocol); [/c]

  1. int domain – PF_INET for IPv4, PF_INET6 for IPv6
  2. int type – SOCK_STREAM for TCP, SOCK_DGRAM for UDP.
  3. int protocol – set to zero, so the function will choose the right protocol, according to the other parameters.

But before running to your text editor and calling the function, let me make you happy!! All those parameters are provided from the addrinfo struct which getaddrinfo() filled out for us!! See why its a magical function? :)

So, using those resources, the socket() call is like this :

[c light="true"]

int s;

s = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol);

[/c]

I need a port!

The next step, is to bind our socket  ( if needed ) to a local port and then listen on it for incoming connections.

[c light="true"]int bind(int sockfd, struct sockaddr *my_addr, int addrlen);[/c]

Return Value

bind() will return -1 on error, and set errno accordingly.

to understand how it works, here is an example :

[c]#include <stdio.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>

int main() {
struct addrinfo hints, *res;
int sockfd;
// first, load up address structs with getaddrinfo():
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;  // use IPv4 or IPv6, whichever
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;     // fill in my IP for me

getaddrinfo(NULL, "3490", &hints, &res);

// make a socket:

sockfd = socket(res->ai_family, res->ai_socktype, res->ai_protocol);

// bind it to the port we passed in to getaddrinfo():

bind(sockfd, res->ai_addr, res->ai_addrlen);
close(socket);
freeaddrinfo(res);
return 0;
}

[/c]

By passing AI_PASSIVE to hints.ai_flags we instruct that we will bind to the host where the program is running, and for this reason, the first argument of getaddrinfo() is NULL.
If we wanted to bind on another IP or host, we define it as the first argument of getaddrinfo() and bypass the AI_PASSIVE statement. Right now, our program is not ready to recieve connections, it is just binded on a port. How to listen() on this port will be explained later. Also, keep in mind that binding on ports below 1024 is not allowed, unless you are superuser. All other ports, 1024 to 65535 can be used by you, without superuser privilege, unless they are used by another program.

Connection Initialized…

So, now we are allowed to connect to a remote IP address / hostname ( or even local! ). This is achieved using the connect() function.

[c light="true"]int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);[/c]

  1. int sockfd – The socket file descriptor returned from a socket() call.
  2. struct sockaddr *serv_addr – a sockaddr structure containing the IP address and port.
  3. int addrlen – The number in bytes of the server address structure.

Lucky for us, arguments 2 and 3, are provided from the getaddrinfo() call! Yeah!

Return Value

If connect() was unsuccessful it returns -1 and sets errno accordingly. We will cover how to read errno later.

send() and recv()

Now that we are connected to a remote host, we can send() data to him and he can then recv() our data. Lets see the prototypes :

[c light="true"]int send(int sockfd, const void *msg, int len, int flags);[/c]

  1. int sockfd – The file descriptor returned by socket()
  2. void *msg – Pointer to the data to be sent.
  3. int len – Length of msg in bytes.
  4. int flags – Set to zero.

Return Value

send() will return the number of bytes sent, which might not be same as len! So it’s our responsibility to send all the remaining data. The good news is that packets of size 1kB are usually packed into one packet. Now lets see recv().

If there was an error, -1 will be returned, and errno will be set accordingly.

[c light="true"]int recv(int sockfd, void *buf, int len, int flags);[/c]

  1. int sockfd – The file descriptor returned by socket()
  2. void *buf – A buffer where data read are written.
  3. int len – Length of buf in bytes.
  4. int flags – Set to zero.

Return Value

recv() will return the number of bytes read, which might not be all the data the sender wanted to send. For this reason, zero is returned in case where the connection has been closed, so that we can assume that no more data are to be read.

In case of error, recv() returns -1 and sets errno accordingly.

A lot of informations these are, right? Lets sum up all those information into a real example.

Server – Client example

What’s the best way to put all together what we learned? :)

Server that waits for connections, and prints the message it recieves :

[ server.c ]

[c light="true"]

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#define CON_NUM 10
#define MAX_IPV4_SIZE 15

int main(int argc, char** argv) {
int sockfd, new_fd;
struct addrinfo hints, *servinfo;
struct sockaddr_in their_addr;
socklen_t sin_size;
char *buff = (char*)malloc(1024);
char ip[MAX_IPV4_SIZE]; // max would be lets say 111.111.111.111 = 3×4 ( nums ) + 3×1 ( dots ) = 15
int rc;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

if (argc != 2) {
printf("Usage : %s PORT\n", argv[0]);
return -1;
}

if ((rc = getaddrinfo(NULL, argv[1], &hints, &servinfo)) != 0) {
printf("Error at getaddrinfo() : %s\n", gai_strerror(rc));
return 1;
}

if ((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf("Error at socket() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
return 1;
}

if (bind(sockfd, servinfo->ai_addr, servinfo->ai_addrlen) == -1) {
printf("Error at bind() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}

if (listen(sockfd, CON_NUM) == -1) {
printf("Error at listen() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}
sin_size = sizeof their_addr;
while(1) {
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
printf("Error at accept() : %s\n", strerror(errno));
continue;
}
inet_ntop(their_addr.sin_family, (struct sockaddr*)&their_addr.sin_addr, ip, sizeof ip);
printf("Got connection from %s\n", ip);
int j = 1;
while (1) {
j = recv(new_fd, buff, 1024, 0);
if ( j == 0 )
break;
if ( j == -1 ) {
printf("Error at recv() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}
printf("Recieved : %s\n", buff);
}
}
freeaddrinfo(servinfo);
close(sockfd);
close(new_fd);
return 0;
}

[/c]

Client that send’s a msg to a server.
[ client.c ]

[c]
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#define HOSTNAME "localhost"
#define PORT "1235"

int main(int argc, char** argv) {
int status, sock, bytes_sent;
struct addrinfo hints, *servinfo;
char msg[] = "hello!!";
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

//Not correct usage, print help and exit.
if (argc != 3) {
printf("Usage : %s HOSTNAME PORT\n", argv[0]);
return -1;
}
//get info about remote host.
if ((status = getaddrinfo(argv[1], argv[2], &hints, &servinfo)) != 0) {
printf("Error during getaddrinfo() : %s\n", gai_strerror(status));
return -1;
}
//Initialize socket.
if ((sock = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf(" Error during socket() : %s\n", strerror(errno));
freeaddrinfo(servinfo); //free servinfo allocated space and exit.
return -1;
}
//connect to remote host.
if (connect(sock, servinfo->ai_addr, servinfo->ai_addrlen) == -1 ) {
printf("Error during connect() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sock); //Also close the socket.
return -1;
}
if ( (bytes_sent = send(sock, msg, strlen(msg), 0)) == -1 ) {
printf("Error during send() : %s\n", strerror(errno));
freeaddrinfo(servinfo);
close(sock);
return -1;
}

printf("Sent %d bytes.\n", bytes_sent);
freeaddrinfo(servinfo);
close(sock);
return 0;
}</pre>
[/c]

Resources : beej.us

Incoming Part 2 : Defining IPv6, how to make your networking application, IPv6 compatible, and IPv4 backwards compatible.

Incoming Part 3 : Converting all this bunch of code, into pretty C++ Class! Don’t miss them!

As always, you can subscribe via RSS or follow wedevblog on twitter for the latest development posts!

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netdb.h>
#include <arpa/inet.h>
#define CON_NUM 10
#define MAX_IPV4_SIZE 15int main(int argc, char** argv) {
int sockfd, new_fd;
struct addrinfo hints, *servinfo;
struct sockaddr_in their_addr;
socklen_t sin_size;
char *buff = (char*)malloc(1024);
char ip[MAX_IPV4_SIZE]; // max would be lets say 111.111.111.111 = 3×4 ( nums ) + 3×1 ( dots ) = 15
int rc;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE;

if (argc != 2) {
printf(“Usage : %s PORT\n”, argv[0]);
return -1;
}

if ((rc = getaddrinfo(NULL, argv[1], &hints, &servinfo)) != 0) {
printf(“Error at getaddrinfo() : %s\n”, gai_strerror(rc));
return 1;
}

if ((sockfd = socket(servinfo->ai_family, servinfo->ai_socktype, servinfo->ai_protocol)) == -1) {
printf(“Error at socket() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
return 1;
}

if (bind(sockfd, servinfo->ai_addr, servinfo->ai_addrlen) == -1) {
printf(“Error at bind() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}

if (listen(sockfd, CON_NUM) == -1) {
printf(“Error at listen() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}
sin_size = sizeof their_addr;
while(1) {
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
printf(“Error at accept() : %s\n”, strerror(errno));
continue;
}
inet_ntop(their_addr.sin_family, (struct sockaddr*)&their_addr.sin_addr, ip, sizeof ip);
printf(“Got connection from %s\n”, ip);
int j = 1;
while (1) {
j = recv(new_fd, buff, 1024, 0);
if ( j == 0 )
break;
if ( j  == -1 ) {
printf(“Error at recv() : %s\n”, strerror(errno));
freeaddrinfo(servinfo);
close(sockfd);
return -1;
}
printf(“Recieved : %s\n”, buff);
}
}
freeaddrinfo(servinfo);
close(sockfd);
close(new_fd);
return 0;
}

  • Share/Bookmark
Categories: dev Tags: , , , ,