Network Programming

dingdongboomNetworking and Communications

Oct 27, 2013 (4 years and 11 days ago)

101 views

Network Programming

Sockets and Winsock

Please Be Responsible


We all know that the Internet is full of
security holes


most of them do not require any technical
expertise to exploit.


Security = Inconvenience or Inaccessibility


the more systems that are hacked the harder it
will be to get system administrators to offer
services.


Federal Laws are in place and are being
enforced



Host
-
dependent Data
Representation


Big Endian and Little Endian


How do we store the integer 0x12345678 ?


0x12

0x34

0x56

0x78

0x101

0x102

0x103

0x100

0x78

0x56

0x34

0x12

0x101

0x102

0x103

0x100

Big Endian

Little Endian

Big and Little Endian Users*


Big Endian


PowerPc


Sun Sparc


HP Workstation


Little Endian


Dec Alpha


Intel Pentium

Some systems (MIPS 2000 and Intel i860) can use
either big endian or little endian. The Intel i860
can even change modes while a program is
running!

*Source: Unix network programming, W. Richard Stevens

Network Protocols Must Adopt
One of the Two Byte Orders


Network Byte Order


The protocol byte order


Host Byte Order


The native machine byte order


Conversion Functions


htons : convert 16
-
bit value from host byte order to
network byte order. (ntohs provides the inverse)


htonl: convert 32
-
bit value from host byte order to
network byte order. (ntohl provides the inverse)


Sockets


Machines can talk to each other regardless
of type


Provides a relatively simple API that will
work with many different protocols


Has become a standard for network
programming across platforms

Making a Connection To A
Server from a Client


socket() provides the client with a socket


Specifies protocol and service type


Protocol is typically Internet (AF_INET)


Service is typically SOCK_STREAM (for reliable
connection
-
oriented service or SOCK_DGRAM (for
unreliable connectionless service)


connect()


Specifies ip address and port number of server.

Starting a server


socket()


same as client


bind()


specify address family, IP address,
and port number


listen()


specify the number of clients that
can be waiting for service (not the total
number of clients)


accept()


wait for someone to connect

WinSock


Derived from Berkeley Sockets (Unix)


includes many enhancements for programming
in the windows environment


Open interface for network programming
under Microsoft Windows


API freely available


Multiple vendors supply winsock


Source and binary compatibility


Collection of function calls that provide
network services


gethostname()


Get the name of the host the program is
running on.


int gethostname(char *hostname, int
bufferLength)


Upon return hostname holds the name of the host


bufferLength provides a limit on the number of
bytes that gethostname can write to hostname.

Domain Name Library Routine

(gethostbyname)


gethostbyname(): Given a host name (such as
acavax.lynchburg.edu) get host information.



struct hostent* getbyhostname(char *hostname)


char* h_name; // official name of host


char** h_aliases; // alias list


short h_addrtype; // address family (e.g., AF_INET)


short h_length; // length of address (4 for AF_INET)


char** h_addr_list; // list of addresses (null pointer
terminated)



unsigned long inet_addr(char *address);


converts address in dotted form to a 32
-
bit
numeric value in network byte order


(e.g., “128.173.41.41”)


char* inet_ntoa(struct in_addr address)


struct in_addr


address.S_addr is the long int representation



Internet Address Library Routines

(inet_addr() and inet_ntoa())

Internet Address Library Routines

(gethostbyaddr)


Get the name of the host the program is
running on.


struct hostent* gethostbyaddr(char *address, int
addressLength, int type)


address is in network byte order


addressLength is 4 if type is AF_INET


type is the address family (e.g., AF_INET)

Differences Between Berkeley Sockets and WinSock

Berkeley


WinSock


bzero()



memset()


close()



closesocket()


read()



not required


write()



not required


ioctl()



ioctlsocket()


Additional Features of WinSock 1.1



WinSock supports three different modes


Blocking mode


socket functions don’t return until their jobs are done


same as Berkeley sockets


Nonblocking mode


Calls such as accept() don’t block, but simply return a
status


Asynchronous mode


Uses Windows messages


FD_ACCEPT
-

connection pending


FD_CONNECT
-

connection established


etc.



WinSock 2


Supports protocol suites other than TCP/IP


DecNet


IPX/SPX


OSI


Supports network
-
protocol independent
applications


Backward compatible with WinSock 1.1


WinSock 2 (Continued)


Uses different files


winsock2.h


different DLL (WS2_
-
32.DLL)


API changes


accept() becomes WSAAccept()


connect() becomes WSAConnect()


inet_addr() becomes WSAAddressToString()


etc.

Basic Socket Calls

(socket)

// Berkeley form

int socket(int family


int type,



int protocol);


// WinSock form

SOCKET socket (int family,






int type,






int protocol);


socket (continued)

SOCKET socket (int family,





int type,


int protocol);


family is address family


AF_INET // internet protocols


AF_UNIX // unix internal protocols


AF_NS // Xerox NS protocols


AF_IMPLINK // Interface Message Processor


type is


SOCK_STREAM // stream socket


SOCK_DGRAM // datagram socket


SOCK_RAW // raw socket


protocol is usually zero in applications programming




main(int argc, char** argv)

{


const int expectedArguments = 1;


if (argc != expectedArguments+1)


{


cerr << “usage: << argv[0] << “<serverName>” << endl;


}


else


{


cerr << “server name is “ << argv[1] << endl;


// The rest of the client code goes here


}

}

Basic Socket Calls

(bind)

// Berkeley form

int bind(int sockfd


struct sockaddr* addr,



int addrLen);


// WinSock form

int bind(SOCKET sockfd


struct sockaddr* addr,



int addrLen);


bind (continued)

int bind (SOCKET sockfd,






struct sockaddr* addr,






int addrLen);


sockfd was returned from the socket() call


addr is pointer to a sockaddr_in structure that
contains the server IP address and port number


struct sockaddr_in


short sin_family // address family


u_short sin_port // port number


struct in_addr sin_addr //IP address (32
-
bits)


addrLen
-

sizeof (struct sockaddr_in)

Basic Socket Calls

(listen)

// Berkeley form

int listen(int s


int backlog);


// WinSock form

int listen (SOCKET s,






int backlog);


listen (continued)

int listen (SOCKET s,




int backlog);


s was returned from the socket() call


1<=backlog<=5


Backlog specifies the number of connection requests
that may be simultaneously waiting for service.


This is NOT the number of clients that can be
receiving service simultaneously.




Basic Socket Calls

(accept)

// Berkeley form

int accept(int s


struct sockaddr* addr,



int* pointerToAddrLen);


// WinSock form

SOCKET accept (SOCKET s,






struct sockaddr* addr,






int* pointerToAddrLen);


accept (continued)

SOCKET accept (SOCKET s,






struct sockaddr* addr,






int* pointerToAddrLen);


s was returned from the socket() call


addr is pointer to a sockaddr structure that will
contain the client information


struct sockaddr


unsigned short sa_family // Address Family

»
AF_INET
, AF_UNIX, AF_NS, AF_IMPLINK


char sa_data[14] // up to 14 bytes of protocol
-
specific
address


PointerToAddrLen can be set by accept


The returned socket provides communication with
the client.




Basic Socket Calls

(connect)

// Berkeley form

int connect(int s


struct sockaddr* addr,



int sizeOfAddr);


// WinSock form

int connect (SOCKET s,






struct sockaddr* addr,






int sizeOfAddr);


connect (continued)

int connect (SOCKET s,






struct sockaddr* addr,






int sizeOfAddr);


s was returned from the socket() call


addr is pointer to a sockaddr structure that will
contain the server information


struct sockaddr_in


short sin_family // address family


u_short sin_port // port number


struct in_addr sin_addr //IP address (32
-
bits)


sizeOfAddr is sizeOf(struct sockaddr)




Basic Socket Calls

(send)

// Berkeley form

int send(int s


const char* bytesToSend,



int nBytes,




int flags);


// WinSock form


int send (SOCKET s,




const char* bytesToSend,




int nBytes,





int flags);


send (continued)

int send (SOCKET s,



const char* bytesToSend,



int nBytes,


int flags);


s was returned from the socket() call


bytesToSend is a pointer to the data to send


nBytes is the number of bytes to send


flags


e.g., MSG_OOB


Note: There is no guarantee that send will send all the data requested.
The number of bytes that send actually transmits is returned as a the
result of the function. It may be necessary to call send repeatedly in a
loop to achieve the desired result.




send (continued)

// Sample code that shows repeated calls to send

int mustSend (SOCKET s,




const char* bytesToSend,




int nBytes,


int flags)

{


int bytesSent = 0;


while(bytesSent < nBytes)


{


bytesSent += send(s, bytesToSend+bytesSent, nBytes
-
bytesSent,
flags);


}


return(bytesSent);

}


Basic Socket Calls

(recv)

// Berkeley form

int recv(int s


char* bytesToReceive,



int nBytes,




int flags);


// WinSock form


int recv(SOCKET s,




char* bytesToReceive,




int nBytes,





int flags);


recv (continued)

int recv (SOCKET s,



char* bytesToReceive,




int nBytes,


int flags);


s was returned from the socket() call


bytesToReceive is a pointer to the data buffer


nBytes is the maximum number of bytes to receive


flags


e.g., MSG_OOB


Note: There is no guarantee that recv will recv all the data requested.
The number of bytes that recv actually received is returned by the
function. It may be necessary to call recv repeatedly in a loop to
achieve the desired result.




while( (*_readPtr != _delimiter) &&


(fieldCursor < maxFieldLength
-
1)


)


{


if (_charsInReadBuffer > 0) // Is there data to read?


{


field[fieldCursor] = *_readPtr; // Copy read data


++fieldCursor;


++_readPtr;


--
_charsInReadBuffer;


}



// Do we need to read more data?


while (_charsInReadBuffer == 0)


{


_charsInReadBuffer = recv(_socketfd, _readBuffer,


maxFieldLength, 0);


_readPtr = _readBuffer;


}


}


Basic Socket Calls

(write)

// Berkeley form

int write(int s


const char* bytesToSend,



int nBytes);


// WinSock form

// Not necessarily supported

// Uses Berkeley form when supported


write (continued)

int write (int s,



char* bytesToSend,



int nBytes);


s was returned from the socket() call


bytesToSend is a pointer to the data to send


nBytes is the number of bytes to send



Note: There is no guarantee that write will send all the data requested.
The number of bytes that write actually transmits is returned as a the
result of the function. It may be necessary to call write repeatedly in a
loop to achieve the desired result.




Basic Socket Calls

(read)

// Berkeley form

int read(int s


char* bytesToReceive,



int nBytes);


// WinSock form


// Not necessarily supported

// Uses Berkeley form when supported

read (continued)

int read(SOCKET s,



char* bytesToReceive,




int nBytes);


s was returned from the socket() call


bytesToReceive is a pointer to the data buffer


nBytes is the maximum number of bytes to receive


Note: There is no guarantee that read will read all the data requested.
The number of bytes that read actually received is returned by the
function. It may be necessary to call read repeatedly in a loop to
achieve the desired result.




Basic Socket Calls

(shutdown)

// Berkeley form

int shutdown(int s, int howto);


// WinSock form

int shutdown(Socket s, int howto);

shutdown (continued)

int shutdown(SOCKET s, int howto);


s was returned from the socket() call


howto


SHUT_RD
-

shut down just the read direction. No more reads or
recvs can be issued on this socket. However, writes and sends can
still be used.


SHUT_WR
-

shutdown just the write direction. No more writes and
sends can be issued on this socket. However, reads and recvs can still
be used.


SHUT_RDWR
-

this shuts down both directions. No more data can
be transmitted using the socket. The socket still must be closed.



Note: shutdown will terminate data transmission regardless of the
socket reference count (i.e., even if other threads haven’t yet
closed the socket.)



Basic Socket Calls

(close/closesocket)

// Berkeley form

int close(int s);


// WinSock form

int closesocket(Socket s);

closesocket (continued)

int closesocket(SOCKET s);


s was returned from the socket() call


Note: There is no guarantee that read will read all the data requested.
The number of bytes that read actually received is returned by the
function. It may be necessary to call read repeatedly in a loop to
achieve the desired result.




Basic Socket Calls

(sendto)

// Berkeley form

int sendto(int s


const char* bytesToSend,



int nBytes,


int flags,




struct sockaddr *to,




int sizeOfSockaddr
);


// WinSock form


int sendto(SOCKET s,




const char* bytesToSend,



int nBytes,



int flags,


struct sockaddr *to,




int sizeOfSockaddr
);

sendto (continued)

int sendto (SOCKET s,



const char* bytesToSend,



int nBytes,


int flags


struct sockaddr *to,



int sizeOfSockaddr
);


to is a struct sockaddr_in


struct sockaddr_in


short sin_family // address family


u_short sin_port // port number


struct in_addr sin_addr //IP address (32
-
bits)



sizeOfSockaddr is sizeof(struct sockaddr_in)


Note: Although this function can be used with TCP connected sockets it is
really designed for use with UDP connectionless sockets. There is no
guarantee that data sent with a successful send will arrive at its destination.


Basic Socket Calls

(recvfrom)

// Berkeley form

int recvfrom(int s


char* receivedData,



int nBytes,


int flags,




struct sockaddr *from,




int sizeOfSockaddr
);


// WinSock form


int recvfrom(SOCKET s,




char* receivedBytes,



int nBytes,



int flags,


struct sockaddr *from,




int sizeOfSockaddr
);

recvfrom (continued)

int recvfrom (SOCKET s,



char* receivedData,



int nBytes,


int flags


struct sockaddr *from,



int sizeOfSockaddr
);


to is a struct sockaddr_in


struct sockaddr_in


short sin_family // address family


u_short sin_port // port number


struct in_addr sin_addr //IP address (32
-
bits)



sizeOfSockaddr is sizeof(struct sockaddr_in)


Note: Although this function can be used with TCP connected sockets it is
really designed for use with UDP connectionless sockets. There is no
guarantee that data sent with a successful send will arrive at its destination.


Basic System Calls

(fork)

// Berkeley form

int fork();


// WinSock form

// not necessarily available under windows

fork (continued)

int fork();


Fork creates a new process


Typically the new process handles a client request while
the original process continues waiting for new clients.




for( ; ; )


{


/* Wait for a connection. */


clilen = sizeof(cli_addr);


newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen);



if (newsockfd < 0)


{


cerr << “accept failed, errno = “ << errno << endl;


}


else


{


// Create a new process to process the request


int pid = 0;


pid = fork();


// The child process handles the request


if (pid != 0)


processServerRequest(newsockfd);


}


}