sparty 0 Newbie Poster

Ive recently spent a lot of time using BSD sockets in Linux to do socket programming. I have written this howto with samples to show a person how to send a message buffer. Feel free to comment on this and correct anything that you think i have said wrong or add your input.


Client side(side trying to connect):

Create a socket: socket(AF_INET, SOCK_STREAM, 0);
AF_INET:The field specifies which communications domain in which the socket will be created: In case of ethernet you want AF_INET(PF_INET will work as well)
SOCK_STREAM:This specifies the type of socket to be made(this is where you differentiate between(TCP & UDP) in the case of TCP this argument should be SOCK_STREAM.
0: This states which protocol is to be used on the type of socket made with SOCK_STREAM. If the argument is '0' it will use the default protocol for the type of socket you created
The function returns a file descriptor.

Optional:set socket options: setsockopt(fd, SOL_SOCKET, SO_REUSEADDR,&flags, sizeof(flags))).. this function allows you to set many options of the socket, we are using it so we can immediately re-open it. Without this it wont let you re-bind the socket for a small amount of time.
fd: The name of the file descriptor that you want to change the options of.. this is the value returned by socket()
SOL_SOCKET:This is for specifying which level you want to specify the options for. We are setting them at the socket level so we use SOL_SOCKET.
SO_REUSEADDR:This argument is the options that you wish to set. In our case this allows immediate re-use of the socket
&flag: Pointer to a value that will enable/disable the option. So in our case we want it enabled, initialized int flag=1;
sizeof(flag):This is requesting the size of the option.

Initialize sockaddr_in struct:This struct contains information about, among other things, the address of the socket.
ServerAddress.sin_family=AF_INET :AF_INET in this situation makes the address you are sending to IPv4
ServerAddress.sin_port= htons(2005) :sets the port number of the port that you are sending your information to, the values can vary on different systems, but values in the 2000s are typically alright for Linux systems.
ServerAddress.sin_addr.s_addr=inet_addr("192.168.0.1"):IP address of the server that you are sending your information to.

Connect to the server: connect(fd,(sockaddr *)&ServerAddress ,sizeof(ServerAddress)): connect to the server based on the attributes that you set in the sockaddr_in structure . The server has to be listening by this point. Once connected you can send back and forth without re-doing any of the previous steps... until you close the socket.
fd:File descriptor returned by socket().
(sockaddr *) &ServerAddress: sockaddr_in struct needs to be cast as sockaddr
sizeof(ServerAddress): Size of the address attributes struct.

Send your info: send(fd, messageBuffer, sizeof(messageBuffer), 0): again this differentiates TCP from UDP, UDP utilizes the sendto():
fd: again same as before
messgeBuffer:pointer to a buffer containing your info
sizeof(messageBuffer): size of your buffer
0: is the place for flags, but in our case we dont need to use any of them.


Simple Sample Client:

//---------------------------------------------------------------------
//Client that will send messages through the TCP protocol
//---------------------------------------------------------------------
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#include <arpa/inet.h>
//---------------------------------------------------------------------
using namespace std;

//Structure Declarations-----------------------------------------------
struct sockaddr_in ServerAddress;			

//Variable Declarations-----------------------------------------
int fd;	//Socket File Descriptors
int size_sent;
int connection_ok;
char messageBuffer[12]="TCP PROTOCOL";
int result = 0;
//Main Function--------------------------------------------------------
int main()
{
	fd=socket(AF_INET, SOCK_STREAM, 0);
	if(fd==-1)
	{
		cerr<<"error couldnt create socket"<<endl;
		exit(1);
	}

	ServerAddress.sin_family=AF_INET;
	ServerAddress.sin_port= htons(2005);
	ServerAddress.sin_addr.s_addr=inet_addr("192.168.0.1");

	connection_ok=connect(tcp_fd,(sockaddr *)&ServerAddress ,sizeof(ServerAddress));
	if(connection_ok==-1)
	{
		cerr<<"unable to connect"<<endl;
		exit(1);
	}
	size_sent = send(fd, messageBuffer, sizeof(messageBuffer), 0);
	close(fd);	
	
   	return 0;
}
////////////////////////////////////////////////////////////////////////////////////////////////////////

Server side(side listening for connections):

Create socket: socket(): Same process as above

Optional:setsockopt(): same as above

Set sockaddr_in struct: same as above except for the actual IP address field you want to set it to the IP of the server itself.
myServerAddress.sin_addr.s_addr=htonl(INADDR_ANY): this assignment will automatically set the address to the address of the local machine. you could also do it the same as above, except setting the value manually.

Bind the socket:bind(fd, (sockaddr *) &myServerAddress, sizeof (myServerAddress)) :Binding associates the sockaddr_in values with the socket that you made, so now your socket contains all of the about port/address attributes. This is the socket that you will listen for connections on.
fd:File descriptor returned by socket().
(sockaddr *) &myServerAddress: sockaddr_in struct needs to be cast as sockaddr
sizeof(myServerAddress): Size of the address attributes struct.

Listen on the bound socket:listen(fd, 1024):
fd: file descriptor of the socket you want to listen on, except since we have binded now the socket has all the info we need to know where to listen.
1024:is the backlog aka the number of outstanding connections in the listen queue values can vary based on system.

Accept the connection: accept(fd,(struct sockaddr *)&clientAddress,&clientlength): accept waits for the client to connect
fd:file descriptor of the socket you want to accept connections from.
(struct sockaddr *)&clientAddress: this is a struct that can save the address information of the incoming message.... if you dont want to send anything back this value can be null.
&clientlength: this is the length of the incoming socket info, the length needs to be of type socklen_t... again you can set this to null if you want though

this function returns a new file descriptor so that the old one can continue to listen.

Receive from the new socket:recv(new_fd, messageBuf,sizeof(messageBuf),0))
new_fd:socket descriptor of the new socket that was created by accept().
messageBuf: name of the buffer to save the incoming info
sizeof(messageBuf): size of the received buffer
0:flags we dont need any of these for simple transmission


Simpe Sample Server:

//---------------------------------------------------------------------
//Client that will receive messages through the TCP protocol
//---------------------------------------------------------------------
#include <iostream>
#include <stdio.h>
#include <stdlib.h>
#include <ctype.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <sys/time.h>
#include <arpa/inet.h>
//---------------------------------------------------------------------
using namespace std;

struct sockaddr_in myServerAddress; //object that will hold the servers address

//Variable Declarations-----------------------------------------
int fd;
int new_fd;
int listener;
int binder;
int msg_size;
char messageBuffer[12];
socklen_t clientlength;

//Main Function--------------------------------------------------------
int main()
{
	fd=socket(AF_INET, SOCK_STREAM, 0);
	int flags=1;
	setsockopt(tcp_fd, SOL_SOCKET, SO_REUSEADDR,&flags, sizeof(flags));
	myServerAddress.sin_family=AF_INET;
	myServerAddress.sin_port=htons(2010);

	myServerAddress.sin_addr.s_addr=htonl(INADDR_ANY);
	binder=bind(fd,(struct sockaddr *)&myServerAddress, sizeof(myServerAddress));
	if(binder==-1)
	{
		cerr<<"error couldnt bind"<<endl;
		exit(1);
	}
	listener=listen (tcp_fd, 1024);//listen for incoming connections
	if(listener==-1)
	{
		cerr<<"error couldnt listen"<<endl;
		exit(1);
	}	
	new_fd=accept(fd, NULL, NULL);
	msg_size = recv(new_fd, messageBuffer, sizeof(messageBuffer), 0);
	close(new_fd);
	close(fd);
return 0;
}
Be a part of the DaniWeb community

We're a friendly, industry-focused community of developers, IT pros, digital marketers, and technology enthusiasts meeting, networking, learning, and sharing knowledge.