Breif intro on BSD sockets in C++
Breif intro on BSD sockets in C++
OK, alot of people log onto #help and ask about socket programming like err, "I cant get my socket to connect" or "my program wont read data", etc. I will give a short tutorial on how to make a basic program which sends/receives using BSD sockets.
To start off you will need to include the following headers:
#include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h>
They provide you with the following functions needed for simple connections:
socket(int domain, int type, int protocol)
bind(int sockfd, struct sockaddr *my_addr, int addrlen)
connect(int sockfd, struct sockaddr *server_addr, int addrlen)
listen(int s, int backlog)
accept(int socket, struct sockaddr *addr, int *addrlen)
read(int fd, void *buffer, size_t count)
recv(int s, void *buf, int len, unsigned int flags)
write(int fd, const void*buffer, size_t count)
send(int s, const void *msg, int len, unsigned int flags)
gethostbyname(const char *name)
And the structures: Hostent sockaddr_in sockaddr
There are many more but these are all you need for a simple client or server for now.
So after adding the headers to the source you should have something that looks like this:
/* add headers */ using namespace std;
int main() { return 0; }
To start you will create a socket by adding int sock; above the return 0;. Under sock you will turn it into a socket by using:
sock = socket(PF_INET, SOCK_STREAM, 0);
Explanation: This creates a socket using the PF_INET domain, the socket will be using a secure STREAM type using protocol TCP.
You will then declare the options that the socket will use for connection, first you declare a place to hold the options using:
sockaddr_in addr;
NOTE I got confused with this when i first learned about sockets, addr DOES NOT have to be called addr, i use that because it describes best what the structure does, for example you can do this and it would work the same:
sockaddr_in myl33tz0r_4ddr
After declaring the structure you will need to fill it with the information the socket will use:
addr.sin_family = AF_INET; addr.sin_port = htons(6667); addr.sin_addr.s_addr = inet_addr("irc.hackthissite.org");
ALTERNATE METHOD You can also declare the address by using gethostbyname:
hostent *hp; hp = gethostbyname("irc.hackthissite.org"); addr.sin_addr = *((in_addr *)hp->h_addr);
After using the method of your choice (I recommend gethostbyname()) you will be able to connect the socket using the information in the structure that you have just filled:
connect(sock, (const sockaddr *) &addr, sizeof(addr));
This will connect your socket with the address in addr.sin_addr.s_addr using the port from addr.sin_port.
NOTE You will need to check the return values of all the functions (socket(), connect(), etc) to make sure an error didn't occur, the return value you don't want is -1 because it means there was an error and the socket will not be able to function. To check for errors just define an integer variable and add it to the function like this:
int return_value; return_value = connect(sock, (const sockaddr ) &addr, sizeof(addr)); if(return_value == -1) { / sort the error */ }
Now that you have connected to the server you are ready for send/receive, this is where it gets easy.
for(;;) { char buffer[1000]; read(sock, buffer, sizeof(buffer)); cout << buffer << endl; }
You will see that the program displays the information sent by the server declared in addr.sin_addr.s_addr. To send information just do:
for(;;) { char buffer[1000]; /* do input handling of buffer */ write(sock, buffer, sizeof(buffer)); }
Closing up: Now that you have created a program that sends/receives you will most probably need to shut the socket down at one time, to do this use the close() function:
close(sock);
This closes Input/Output of the socket.
Moving on: There are MANY other functions that you can use which i havent added here, you will also realise that your program will not send and receive at the same time, this can be sorted by using pthreads (splitting the program into multiple threads working parallel) or the fork() function (creating another process). A good project to try would be an IRC Bot (i have made this tutorial the start of the bot) or a server maybe (i have not gone into the process of making a server in this tutorial but it uses additional functions bind(), listen() and accept()).
Full program:
#include <iostream> #include <sys/types.h> #include <sys/socket.h> #include <unistd.h> #include <netinet/in.h> #include <arpa/inet.h> #include <netdb.h> using namespace std;
int main() { char recv_buffer[1000]; char send_buffer[1000]; int sock; int ret_val; sockaddr_in addr; hostent *hp;
sock = socket(PF_INET, SOCK_STREAM, 0);
addr.sin_family = AF_INET;
addr.sin_port = htons(6667);
hp = gethostbyname("irc.hackthissite.org");
addr.sin_addr = *((struct in_addr *) hp->h_addr);
ret_val = connect(sock, (const sockaddr *) &addr, sizeof(addr));
if(ret_val == -1)
{
cout << "Cannot connect!" << endl;
close(sock);
return 1;
}
for(;;)
{
read(sock, recv_buffer, sizeof(recv_buffer));
cout << recv_buffer << endl;
}
return 0;
}
Article written by: d[o_o]b, known as doob on hts.
Any further questions just go on the irc.hackthissite.org network and talk to me on #help.
richohealey 17 years ago
this is fantastic. lol, it reminds me of the one i wrote on python, but i covered threading as well.
nice work!
ghost 14 years ago
great, I've been looking on a tutorial for this. I found one, but it was terrible and I learned nothing on actually programming, just a lot about how TCP and UDP work… now if only I had time to actually read it right now…