Network Programming Sockets and Winsock Please Be Responsible
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 https: //www. eff. org/issues/cfaa
Host-dependent Data Representation • Big Endian and Little Endian – How do we store the integer 0 x 12345678 ? 0 x 100 0 x 12 0 x 100 0 x 78 0 x 101 0 x 34 0 x 101 0 x 56 0 x 102 0 x 34 0 x 103 0 x 78 0 x 103 0 x 12 Big Endian Little Endian
Big and Little Endian Users* • Big Endian – Power. Pc – Sun Sparc – HP Workstation • Little Endian – Dec Alpha – Intel Pentium Some systems (MIPS 2000 and Intel i 860) can use either big endian or little endian. The Intel i 860 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 (Big Endian in IPv 4) • 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 (not just TCP/IP) • 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
Win. Sock • 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 buffer. Length) • Upon return hostname holds the name of the host • buffer. Length 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)
Internet Address Library Routines (inet_addr() and inet_ntoa()) • 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”) • char* inet_ntoa(struct in_address) – struct in_addr • address. S_addr is the long int representation
Internet Address Library Routines (gethostbyaddr) • Get the name of the host the program is running on. – struct hostent* gethostbyaddr(char *address, int address. Length, int type) • address is in network byte order • address. Length is 4 if type is AF_INET • type is the address family (e. g. , AF_INET)
Differences Between Berkeley Sockets and Win. Sock Berkeley Win. Sock bzero() memset() closesocket() read() not required write() not required ioctl() ioctlsocket()
Additional Features of Win. Sock 1. 1 • Win. Sock 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.
Win. Sock 2 • Supports protocol suites other than TCP/IP – Dec. Net – IPX/SPX – OSI • Supports network-protocol independent applications • Backward compatible with Win. Sock 1. 1
Win. Sock 2 (Continued) • Uses different files – winsock 2. h – different DLL (WS 2_-32. DLL) • API changes – accept() becomes WSAAccept() – connect() becomes WSAConnect() – inet_addr() becomes WSAAddress. To. String() – etc.
Basic Socket Calls (socket) // Berkeley form int socket(int family int type, int protocol); // Win. Sock 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 expected. Arguments = 1; if (argc != expected. Arguments+1) { cerr << “usage: << argv[0] << “<server. Name>” << 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 addr. Len); // Win. Sock form int bind(SOCKET sockfd struct sockaddr* addr, int addr. Len);
bind (continued) int bind (SOCKET sockfd, struct sockaddr* addr, int addr. Len); – 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) – addr. Len - sizeof (struct sockaddr_in)
Basic Socket Calls (listen) // Berkeley form int listen(int s int backlog); // Win. Sock 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* pointer. To. Addr. Len); // Win. Sock form SOCKET accept (SOCKET s, struct sockaddr* addr, int* pointer. To. Addr. Len);
accept (continued) SOCKET accept (SOCKET s, struct sockaddr* addr, int* pointer. To. Addr. Len); – 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 • Pointer. To. Addr. Len 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 size. Of. Addr); // Win. Sock form int connect (SOCKET s, struct sockaddr* addr, int size. Of. Addr);
connect (continued) int connect (SOCKET s, struct sockaddr* addr, int size. Of. Addr); – 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) • size. Of. Addr is size. Of(struct sockaddr)
Basic Socket Calls (send) // Berkeley form int send(int s const char* bytes. To. Send, int n. Bytes, int flags); // Win. Sock form int send (SOCKET s, const char* bytes. To. Send, int n. Bytes, int flags);
send (continued) int send (SOCKET s, const char* bytes. To. Send, int n. Bytes, int flags); – s was returned from the socket() call – bytes. To. Send is a pointer to the data to send – n. Bytes 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 must. Send (SOCKET s, const char* bytes. To. Send, int n. Bytes, int flags) { int bytes. Sent = 0; while(bytes. Sent < n. Bytes) { bytes. Sent += send(s, bytes. To. Send+bytes. Sent, n. Bytes-bytes. Sent, flags); } return(bytes. Sent); }
Basic Socket Calls (recv) // Berkeley form int recv(int s char* bytes. To. Receive, int n. Bytes, int flags); // Win. Sock form int recv(SOCKET s, char* bytes. To. Receive, int n. Bytes, int flags);
recv (continued) int recv (SOCKET s, char* bytes. To. Receive, int n. Bytes, int flags); – s was returned from the socket() call – bytes. To. Receive is a pointer to the data buffer – n. Bytes 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( (*_read. Ptr != _delimiter) && (field. Cursor < max. Field. Length-1) ) { if (_chars. In. Read. Buffer > 0) // Is there data to read? { field[field. Cursor] = *_read. Ptr; // Copy read data ++field. Cursor; ++_read. Ptr; --_chars. In. Read. Buffer; } // Do we need to read more data? while (_chars. In. Read. Buffer == 0) { _chars. In. Read. Buffer = recv(_socketfd, _read. Buffer, max. Field. Length, 0); _read. Ptr = _read. Buffer; } }
Basic Socket Calls (write) // Berkeley form int write(int s const char* bytes. To. Send, int n. Bytes); // Win. Sock form // Not necessarily supported // Uses Berkeley form when supported
write (continued) int write (int s, char* bytes. To. Send, int n. Bytes); – s was returned from the socket() call – bytes. To. Send is a pointer to the data to send – n. Bytes 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* bytes. To. Receive, int n. Bytes); // Win. Sock form // Not necessarily supported // Uses Berkeley form when supported
read (continued) int read(SOCKET s, char* bytes. To. Receive, int n. Bytes); – s was returned from the socket() call – bytes. To. Receive is a pointer to the data buffer – n. Bytes 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); // Win. Sock 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); // Win. Sock 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* bytes. To. Send, int n. Bytes, int flags, struct sockaddr *to, int size. Of. Sockaddr); // Win. Sock form int sendto(SOCKET s, const char* bytes. To. Send, int n. Bytes, int flags, struct sockaddr *to, int size. Of. Sockaddr);
sendto (continued) int sendto (SOCKET s, const char* bytes. To. Send, int n. Bytes, int flags struct sockaddr *to, int size. Of. Sockaddr); – 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) • size. Of. Sockaddr 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* received. Data, int n. Bytes, int flags, struct sockaddr *from, int size. Of. Sockaddr); // Win. Sock form int recvfrom(SOCKET s, char* received. Bytes, int n. Bytes, int flags, struct sockaddr *from, int size. Of. Sockaddr);
recvfrom (continued) int recvfrom (SOCKET s, char* received. Data, int n. Bytes, int flags struct sockaddr *from, int size. Of. Sockaddr); – 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) • size. Of. Sockaddr 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(); // Win. Sock 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) process. Server. Request(newsockfd); } }
- Slides: 49