Socket Programming
Socket Programming
Socket API
kernel space
hardware
Byte Ordering
union { u_int32_t addr; /* unsigned long int, 4 bytes address */ unsigned char c[4]; } un; /* 128.2.194.95 */ un.addr = 0x8002c25f; /* un.c[0] = ? */ c[0] c[1] c[2] c[3]
Big Endian
Sun Solaris, PowerPC, ...
128 95
2 194
194 2
95 128
Little Endian
i386, alpha, ...
Byte Order
Different computers may have different internal representation of 16 / 32bit integer (called host byte order). Examples Big-Endian byte order (e.g., used by Motorola 68000):
#include <netinet/in.h> unsigned unsigned unsigned unsigned long int htonl(unsigned long int hostlong); short int htons(unsigned short int hostshort); long int ntohl(unsigned long int netlong); short int ntohs(unsigned short int netshort);
What is a Socket?
A socket is a file descriptor that lets an application read/write data from/to the network int fd; /* socket descriptor */ if ((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) } perror(socket); exit(1); } socket returns an integer (socket descriptor) fd < 0 indicates that an error occurred socket descriptors are similar to file descriptors AF_INET: associates a socket with the Internet protocol family SOCK_STREAM: selects the TCP protocol SOCK_DGRAM: selects the UDP protocol
TCP Server
For example: web server
Web Server Port 80 TCP
What does a web server need to do so that a web client can connect to it?
IP
Ethernet Adapter
if((fd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { perror(socket); exit(1); } socket returns an integer (socket descriptor) fd < 0 indicates that an error occurred AF_INET associates a socket with the Internet protocol family SOCK_STREAM selects the TCP protocol
/* 1) create the socket */ /* 2) bind the socket to a port */ if(listen(fd, 5) < 0) { perror(listen); exit(1); }
/* 1) create the socket */ /* 2) bind the socket to a port */ /* 3) listen on the socket */ newfd = accept(fd, (struct sockaddr*) &cli, &cli_len); if(newfd < 0) { perror("accept"); exit(1); }
accept returns a new socket (newfd) with the same properties as the original socket (fd) newfd < 0 indicates that an error occurred
newfd = accept(fd, (struct sockaddr*) &cli, &cli_len); if(newfd < 0) { perror("accept"); exit(1); }
Now the server can exchange data with the client by using read and write on the descriptor newfd. Why does accept need to return a new descriptor?
1) create the socket */ 2) bind the socket to a port */ 3) listen on the socket */ 4) accept the incoming connection */ 5) Create a child process to attend the connection */ Child will close fd, and continue communication with client */ parent will close newfd, and continue with accepting connection*/
TCP Client
For example: web client
2 Web Clients
IP
Ethernet Adapter
/* 1) create the socket */ /* 2) connect() to the server */ /* Example: A client could write a request to a server */ if((nbytes = write(fd, buf, sizeof(buf))) < 0) { perror(write); exit(1); }
TCP Client
socket() connect() write() connection establishment data request data reply read() close()
from UNIX Network Programming by Stevens
listen() accept()
end-of-file notification
TCP provides reliable, in-order transfer of bytes (pipe) between client and server
/* client.c */ void main(int argc, char *argv[]) { struct sockaddr_in sad; /* structure to hold an IP address */ int clientSocket; /* socket descriptor */ struct hostent *ptrh; /* pointer to a host table entry */ char Sentence[128]; char modifiedSentence[128]; host = argv[1]; port = atoi(argv[2]); Create client socket, connect to server
clientSocket = socket(PF_INET, SOCK_STREAM, 0); memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */ sad.sin_family = AF_INET; /* set family to Internet */ sad.sin_port = htons((u_short)port); ptrh = gethostbyname(host); /* Convert host name to IP address */ memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length); connect(clientSocket, (struct sockaddr *)&sad, sizeof(sad));
Close connection
close(clientSocket); }
/* Specify the maximum number of clients that can be queued */ listen(welcomeSocket, 10) while(1) {
connectionSocket=accept(welcomeSocket, (struct sockaddr *)&cad, &alen); n=read(connectionSocket, clientSentence, sizeof(clientSentence)); /* capitalize Sentence and store the result in capitalizedSentence*/ n=write(connectionSocket, capitalizedSentence, strlen(capitalizedSentence)+1); close(connectionSocket); } } End of while loop, loop back and wait for another client connection Write out the result to socket
application viewpoint
UDP provides unreliable transfer of groups of bytes (datagrams) between client and server
Client
create socket, clientSocket = DatagramSocket() Create, address (hostid, port=x, send datagram request using clientSocket
read request from serverSocket write reply to serverSocket specifying client host address, port number
/* client.c */ void main(int argc, char *argv[]) { struct sockaddr_in sad; /* structure to hold an IP address */ int clientSocket; /* socket descriptor */ struct hostent *ptrh; /* pointer to a host table entry */ char Sentence[128]; char modifiedSentence[128]; host = argv[1]; port = atoi(argv[2]);
clientSocket = socket(PF_INET, SOCK_DGRAM, 0); /* determine the server's address */ memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */ sad.sin_family = AF_INET; /* set family to Internet */ sad.sin_port = htons((u_short)port); ptrh = gethostbyname(host); /* Convert host name to IP address */ memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
n=recvfrom(serverSocket, clientSentence, sizeof(clientSentence), 0 (struct sockaddr *) &cad, &addr_len ); /* capitalize Sentence and store the result in capitalizedSentence*/ n=sendto(connectionSocket, capitalizedSentence, strlen(capitalizedSentence)+1,0 (struct sockaddr *) &cad, &addr_len); close(connectionSocket); } } End of while loop, loop back and wait for another client connection Write out the result to socket
/* ================================================== */ char buf[1024]; struct packet *pkt; pkt = (struct packet*) buf; pkt->type = htonl(1); pkt->length = htons(2); pkt->checksum = htons(3); pkt->address = htonl(4);
Textbook
Stevens, Unix Network Programming, PHI
Sockets
Sockets provide an interface for programming networks at the transport layer. Network communication using Sockets is very much similar to performing file I/O
In fact, socket handle is treated like file handle. The streams used in file I/O operation are also applicable to socket-based I/O
Socket Communication
A server (program) runs on a specific computer and has a socket that is bound to a specific port. The server waits and listens to the socket for a client to make a connection request.
server Connection request Client
port
Socket Communication
If everything goes well, the server accepts the connection. Upon acceptance, the server gets a new socket bounds to a different port. It needs a new socket (consequently a different port number) so that it can continue to listen to the original socket for connection requests while serving the connected client.
port port
Client server port
Connection
Java Sockets
Server
ServerSocket(1234)
Client
Implementing a Server
1. Open the Server Socket: ServerSocket server; DataOutputStream os; DataInputStream is; server = new ServerSocket( PORT ); 2. Wait for the Client Request: Socket client = server.accept(); 3. Create I/O streams for communicating to the client is = new DataInputStream( client.getInputStream() ); os = new DataOutputStream( client.getOutputStream() ); 4. Perform communication with client Receive from client: String line = is.readLine(); Send to client: os.writeBytes("Hello\n"); 5. Close sockets: client.close(); For multithreaded server: while(true) { i. wait for client requests (step 2 above) ii. create a thread with client socket as parameter (the thread creates streams (as in step (3) and does communication as stated in (4). Remove thread once service is provided. }
Implementing a Client
1. Create a Socket Object:
client = new Socket(server, port_id ); 2. Create I/O streams for communicating with the server.
is = new DataInputStream(client.getInputStream() ); os = new DataOutputStream( client.getOutputStream() );
Run
Run Server on agnee.tezu.ernet.in
java SimpleServer &
Socket Exceptions
try { Socket client = new Socket(host, port); handleConnection(client); } catch(UnknownHostException uhe) { System.out.println("Unknown host: " + host); uhe.printStackTrace(); } catch(IOException ioe) { System.out.println("IOException: " + ioe); ioe.printStackTrace(); }
Throws:
IOException - if an I/O error occurs when opening the socket. SecurityException - if a security manager exists and its checkListen method doesn't allow the operation.
Server Process
Server Threads
Internet
Client 2 Process
Conclusion
Programming client/server applications in Java is fun and challenging. Programming socket programming in Java is much easier than doing it in other languages such as C. Keywords:
Clients, servers, TCP/IP, port number, sockets, Java sockets