Thursday, March 13, 2008

UNIX NETWORK PROGRAMS

/* Some of the files and definitions to be used in the socket programs*/

#include
#include
#include
#include
#include
#include
#include
#define SERV_UDP_PORT 6600
#define SERV_TCP_PORT 5000
#define SERV_HOST_ADDRESS "172.16.0.1"
#define MAXLINE 80
#define UNIXSTR_PATH "unix_sock"
#define UNIXDG_PATH "./unix_srv_dg"
#define UNIXDG_TMP "./dg.xxxxxx"
#define MAXMESG 2048
#define MAX 512
char *pname;

int readn(register int fd,register char *ptr,register int nbytes)
{
int nleft,nread;
nleft=nbytes;
while(nleft>0)
{
nread=read(fd,ptr,nleft);
if(nread<0)
return (nread);
else
if(nread==0)
break;
nleft-=nread;
ptr+=nread;
}
return (nbytes-nleft);
}


int writen(register int fd,register char *ptr,register int nbytes)
{
int nleft,nwritten;
nleft=nbytes;
while(nleft>0)
{
nwritten=write(fd,ptr,nleft);
if(nwritten<0)
return (nwritten);
nleft-=nwritten;;
ptr+=nwritten;
}
return (nbytes-nleft);
}


int readline(register int fd,register char *ptr, register int maxlen)
{
int n,rc;char c;
for(n=1;n {if((rc=read(fd,&c,1))==1){*ptr++=c;if(c=='\n') break;
}
else if(rc==0) {
if(n==1)return 0;
else break;}
else
return -1;}*ptr='\0';return (n);}
str_cli(register FILE *fp,register int sockfd)
{
int n;
char sendline[MAXLINE],recvline[MAXLINE+1];
printf("\nEnter a message: ");
fflush(stdout);
while(1)
{
fgets(sendline,MAXLINE,fp);
if(strlen(sendline)==1)
break;
n=strlen(sendline);
printf("\nClient is sending to server: %s",sendline);
if(writen(sockfd,sendline,n)!=n)
perror("str_cli:writen error from socket");
n=readline(sockfd,recvline,MAXLINE);
printf("Client received from server: %s",recvline);
printf("\nEnter a message to continue or press ENTER to terminate: ");
fflush(stdout);
if(n<0)
perror("str_cli:readline error");
// recvline[n]='\0';
}
if(ferror(fp))
perror("str_cli:error reading file");
}


str_echo(int sockfd)
{
int n;
char line[MAXLINE];
for(; ;)
{
n=readline(sockfd,line,MAXLINE);
printf("\nServer received from client: %s",line);
if(n==0)
return;
else
if(n<0)
perror("str_echo: readline error");
printf("Server echoing back to client:%s",line);
fflush(stdout);
if(writen(sockfd,line,n)!=n)
perror("str_echo:writen error");
}
}

dg_cli(FILE *fp,int sockfd,struct sockaddr *pserv_addr,int servlen)
{
int n;
char sendline[MAXLINE],recvline[MAXLINE+1];
printf("\nEnter a message to send to server: ");
while(fgets(sendline,MAXLINE,fp))
{
if((n=strlen(sendline))==1) exit(0);
printf("\nUDP client is sending to server: %s",sendline);
if(sendto(sockfd,sendline,n,0,pserv_addr,servlen)!=n)
perror("dg_cli:sendto error");
n=recvfrom(sockfd,recvline,MAXLINE,0,(struct sockaddr *)0,(int *)0);
if(n<0)
perror("dg_cli:recvfrom error");
recvline[n]='\0';
printf("UDP client received from: %s",recvline);
fflush(stdout);
printf("\nEnter thenext message to send or ENTER to terminate:");
}
if(ferror(fp))
perror("dg_cli:error reading file");
}


dg_echo(int sockfd,struct sockaddr * pcli_addr,int maxclilen)
{
int n,clilen;
char mesg[MAXMESG];
for( ; ;)
{
clilen=maxclilen;
n=recvfrom(sockfd,mesg,MAXMESG,0,pcli_addr,&clilen);
if(n<0)
perror("dg_echo:recvfrom error");
mesg[n]='\0';
printf("\nUDP server received from client and echoing: %s",mesg);
fflush(stdout);
if(sendto(sockfd,mesg,n,0,pcli_addr,clilen)!=n)
perror("dg_echo:sendto error");

}
}

UNIX NETWORK PROGRAMS

/* CONNECTION ORIENTED(UNIX) CONCURRENT CLIENT */
#include
#include
#include
#include
#include
#define max 80
main(int argc,char *argv[])
{
int sfd,s,i,n,sl;
char buff1[max],buff2[max];
struct sockaddr_un sa;
//pname =argv[0];
sfd=socket(AF_UNIX,SOCK_STREAM,0);
if(sfd<0)
{
printf("CLIENT:SOCKET ERROR");
exit(0);
}
//perror("server:cannot open stream socket");
bzero((char*)&sa,sizeof(sa));
sa.sun_family=AF_UNIX;
strcpy(sa.sun_path,argv[1]);
sl=strlen(sa.sun_path)+sizeof(sa.sun_family);
s=connect(sfd,(struct sockaddr *)&sa,sl);
if(s<0)
{
printf("CLIENT:CANNOT CONNECT");
exit(0);
}
for(i=0;i<10;i++)
{
write(1,"\nENTER MESSAGE:",15);
n=read(0,buff1,20);
write(1,"\nCLIENT HAS SENT:",17);
write(1,buff1,n);
send(sfd,buff1,n,0);
n=recv(sfd,buff2,20,0);
write(1,"\nCLIENT HAS RECEIVED FROM SERVER:",33);
write(1,buff2,n);
}
close(sfd);
exit(0);
}

/* CONNECTION ORIENTED(UNIX) CONCURRENT SERVER*/
#include
#include
#include
#include
#include
#define max 80
main(int argc,char *argv[])
{
int sfd,nsfd,pid,n,i,sl,cl;
char buff[max];
struct sockaddr_un ca,sa;
sfd=socket(AF_UNIX,SOCK_STREAM,0);
if(sfd<0)
{
printf("SERVER:SOCKET ERROR");
exit(0);
}
bzero((char *)&sa,sizeof(sa));
sa.sun_family=AF_UNIX;
strcpy(sa.sun_path,argv[1]);
sl=strlen(sa.sun_path)+sizeof(sa.sun_family);
if(bind(sfd,(struct sockaddr *)&sa,sl)<0)
{
printf("SERVER:BIND FAILURE");
exit(0);
}
listen(sfd,5);
for(;;)
{
write(1,"\nSERVER:WAITING....",19);
fflush(stdout);
cl=sizeof(ca);
nsfd=accept(sfd,(struct sockaddr*)&ca,&cl);
if(nsfd<0)
{
printf("SERVER:ACCEPT ERROR");
exit(0);
}
pid=fork();
if(pid==0)
{
close(sfd);
for(i=0;i<10;i++)
{
n=recv(nsfd,buff,max,0);
buff[n]='\0';
write(1,"\nMESSAGE RECEIVED FROM CLIENT:",32);
write(1,buff,n);
send(nsfd,buff,n,0);
}
}
close(nsfd);
exit(0);
}
}

/* Concurrent TCP client program */

#include "files.h"
main(int argc,char *argv[])
{
int sockfd;
struct sockaddr_in serv_addr;
pname=argv[0];
bzero((char *)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr(SERV_HOST_ADDRESS);
serv_addr.sin_port=htons(SERV_TCP_PORT);
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
perror("client:socket error");
if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
{
perror("client:cant connect to error");
exit(1);
}
for(;;)
{



str_cli(stdin,sockfd);
close(sockfd);
exit(0);
}

/* Concurrent TCP server program */

#include "files.h"
main(int argc,char *argv[])
{
int sockfd,newsockfd,clilen,childpid;
struct sockaddr_in cli_addr,serv_addr;
pname=argv[0];
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
perror("server:cant open stream socket");
bzero((char *)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(SERV_TCP_PORT);
if(bind(sockfd,(struct sockaddr *) &serv_addr,sizeof(serv_addr))<0)
{
perror("server:cant bind local address");
exit(1);
}
listen(sockfd,5);
for( ; ;)
{
clilen=sizeof(cli_addr);
printf("\nServer is waiting for connection requests: ");
fflush(stdout);
newsockfd=accept(sockfd,(struct sockaddr *) &cli_addr,&clilen);
if(newsockfd<0)
{
perror("server:accept error");
exit(1);
}
printf("\nConnection established and communicating with client.....");
fflush(stdout);
if((childpid=fork())<0)
perror("server:fork error");
else if(childpid==0)
{
close(sockfd);
str_echo(newsockfd);
exit(0);
}
close(newsockfd);
}
}


/*Concorent UDP client program */
#include "files.h"
main(int argc,char *argv[])
{
int sockfd;
struct sockaddr_in serv_addr,cli_addr;
pname=argv[0];
bzero((char*)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr(SERV_HOST_ADDRESS);
serv_addr.sin_port=htons(SERV_UDP_PORT);
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0)
perror("client:cant open datagram socket");
bzero((char *)&cli_addr,sizeof(cli_addr));
cli_addr.sin_family=AF_INET;
cli_addr.sin_addr.s_addr=htonl(INADDR_ANY);
cli_addr.sin_port=htons(0);
if(bind(sockfd,(struct sockaddr*)&cli_addr,sizeof(cli_addr))<0)
{
perror("client:cant bind local address");
exit(1);
}
dg_cli(stdin,sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr));
close(sockfd);
exit(0);
}


/* Concurent UDP Server program */
#include "files.h"
main(int argc,char *argv[])
{
int sockfd;
struct sockaddr_in serv_addr,cli_addr;
pname=argv[0];
if((sockfd=socket(AF_INET,SOCK_DGRAM,0))<0)
{
perror("server:cant open datargram socket");
exit(1);
}
bzero((char *)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=htonl(INADDR_ANY);
serv_addr.sin_port=htons(SERV_UDP_PORT);
if(bind(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
{
perror("server:cant bind local address");
exit(1);
}
printf("\nUDP server is waiting........");
fflush(stdout);
dg_echo(sockfd,(struct sockaddr *)&cli_addr,sizeof(cli_addr));
}

UNIX NETWORK PROGRAMS

MEANT FOR MCA II YEAR TELANGANA UNIVERSITY NIZAMABAD


//iterative unix client
#include "files.h"
int main(int argc,char *argv[])
{
int sockfd,servlen;
struct sockaddr_un serv_addr;
bzero((char *) &serv_addr,sizeof(serv_addr));
serv_addr.sun_family=AF_UNIX;
strcpy(serv_addr.sun_path,UNIXSTR_PATH);
servlen=strlen(serv_addr.sun_path) + sizeof(serv_addr.sun_family);

/* Open a socket */

if(sockfd=(socket(AF_UNIX,SOCK_STREAM,0))<0)
perror("Client: Can't open socket");
/* Connect to the server */

if(connect(sockfd,(struct sockaddr *) &serv_addr,servlen)<0)
perror("Client:Can't connect to server");
str_cli(stdin,sockfd);
exit(0);
}

/* Example of Iterative server using UNIX domain stream protocol.*/

#include "files.h"
main(int argc,char *argv[])
{
int sockfd,newsockfd,clilen,childpid,servlen;
struct sockaddr_un cli_addr,serv_addr;
pname=argv[0];
if((sockfd=socket(AF_UNIX,SOCK_STREAM,0))<0)
perror("server: cant open stream socket");
bzero((char *)&serv_addr,sizeof(serv_addr));
serv_addr.sun_family=AF_UNIX;
strcpy(serv_addr.sun_path,UNIXSTR_PATH);
servlen=strlen(serv_addr.sun_path)+sizeof(serv_addr.sun_family);
if((bind(sockfd,(struct sockaddr*)&serv_addr,servlen))<0)
{
perror("server:cant bind local address");
exit(1);
}
listen(sockfd,5);
for( ; ;)
{
clilen=sizeof(cli_addr);
newsockfd=accept(sockfd,(struct sockaddr*)&cli_addr,&clilen);
if(newsockfd<0)
{
perror("server:accept error");
exit(1);
}
str_echo(newsockfd);
close(newsockfd);
}
printf("\nServer is exiting.....");
}

SOCKETS

MEANT FOR MCA II YEAR TELANGANA UNIVERSITY NIZAMABAD

WHAT IS SOCKET
•"sockets" are a way to speak to other programs using standard Unix file descriptors.
•Unix programs do any sort of I/O, they do it by reading or writing to a file descriptor.
•A file descriptor is simply an integer associated with an open file. But that file can be a network connection, a FIFO, a pipe, a terminal, a real on-the-disk file, or just about anything else. Everything in Unix is a file! So when you want to communicate with another program over the Internet, do it through a file descriptor.
•To get the file descriptor for network communication, make a call to the socket() system routine. It returns the socket descriptor, and communicate through it using the specialized send() and recv()socket calls.
• the normal read() and write() calls can also be used to communicate through the socket. but send() and recv() offer much greater control over data transmission.
INTERNET SOCKETS
•There are two types of Internet sockets? One is "Stream Sockets"; the other is "Datagram Sockets", which may be referred to as "SOCK_STREAM" and "SOCK_DGRAM", respectively.
•Datagram sockets are sometimes called "connectionless sockets".
STREAM SOCKETS
•Stream sockets are reliable two-way connected communication streams. If you output two items into the socket in the order "1, 2", they will arrive in the order "1, 2" at the opposite end. They will also be error-free.
•What uses stream sockets? the telnet application, uses stream sockets. All the characters you type need to arrive in the same order you type them, Also, web browsers use the HTTP protocol which uses stream sockets to get pages.
•How do stream sockets achieve this high level of data transmission quality? They use a protocol called "The Transmission Control Protocol", known as "TCP". TCP makes sure that data arrives sequentially and error-free.
DATA GRAM SOCKETS
•What about Datagram sockets? Why are they called connectionless? Why are they unreliable? Well, here are some facts: if you send a datagram, it may arrive. It may arrive out of order. If it arrives, the data within the packet will be error-free.
•Datagram sockets also use IP for routing, but they don't use TCP; they use the "User Datagram Protocol", or "UDP".
•Why are they connectionless? it's because you don't have to maintain an open connection as you do with stream sockets. You just build a packet, slap an IP header on it with destination information, and send it out. No connection needed.
•Datagram sockets are generally used either when a TCP stack is unavailable or when a few dropped packets here and there don't mean the end of the Universe.
• Sample applications of datagram sockets are : tftp, bootp, multiplayer games, streaming audio, video conferencing, etc.
•tftp and bootp are used to transfer binary applications from one host to another.
•tftp and similar programs have their own protocol on top of UDP. For example, the tftp protocol says that for each packet that gets sent, the recipient has to send back a packet that says, "I got it!" (an "ACK" packet.) If the sender of the original packet gets no reply in, say, five seconds, he'll re-transmit the packet until he finally gets an ACK. This acknowledgment procedure is very important when implementing reliable SOCK_DGRAM applications.
DATA ENCAPSULATION
•how networks really work, and to show some examples of how SOCK_DGRAM packets are built.
Data Encapsulation.
•Data Encapsulation, it says this: a packet is born, the packet is wrapped ("encapsulated") in a header (and rarely a footer) by the first protocol (say, the TFTP protocol), then the whole thing (TFTP header included) is encapsulated again by the next protocol (say, UDP), then again by the next (IP), then again by the final protocol on the hardware (physical) layer (say, Ethernet).
•When another computer receives the packet, the hardware strips the Ethernet header, the kernel strips the IP and UDP headers, the TFTP program strips the TFTP header, and it finally has the data.
•An ISO-OSI layered model more consistent with Unix might be:
Application Layer (telnet, ftp, etc.)
Host-to-Host Transport Layer (TCP, UDP)
Internet Layer (IP and routing)
Network Access Layer (Ethernet, ATM, or whatever)
these layers correspond to the encapsulation of the original data.
• to build a simple packet, All you have to do for stream sockets is send() the data out. All you have to do for datagram sockets is encapsulate the packet in the method of your choosing and sendto() it out. The kernel builds the Transport Layer and Internet Layer on for you and the hardware does the Network Access Layer.
DATA TYPES USED BY SOCKETS INTERFACE a socket descriptor
• A socket descriptor is Just a regular int. type

sockets

meant for MCA II YEAR STUDENTS TELANGANA UNIVERSITY NIZAMABAD

Socket API
Socket API originated with the 4.2 BSD system released in 1983

Sockets – A way to speak to other programs using UNIX file descriptors.
A file descriptor is an integer associated with an open file.This can be a network connection
Kinds of Sockets-DARPA Internet addresses(Internet Sockets) , Unix Sockets, X.25 Sockets etc
Types of Internet Sockets
SOCK_STREAM uses TCP (Transmission Control Protocol) Connection oriented and Reliable
SOCK_DGRAM uses UDP (User Datagram Protocol)
Connectionless and Unreliable
Structs and Data Handling
A socket descriptor is of type int
Byte ordering
Most significant byte first – Network byte order (Big Endian)
Least significant byte first – Host Byte order ( Little ..)
Socket Structures in Network byte order
struct sockaddr { unsigned short sa_family; // address family, AF_xxx char sa_data[14]; // 14 bytes of protocol address };

struct sockaddr_in { short int sin_family; // Address family
unsigned short int sin_port; // Port number
struct in_addr sin_addr; // Internet address
unsigned char sin_zero[8]; // Same size as struct sockaddr };
Convert the Natives

struct in_addr { unsigned long s_addr; // 32-bit long, or 4 bytes };
If ina is of type struct sockaddr_in
ina.sin_addr.s_addr references the 4-byte IP address (in Network Byte Order


htons() – Host to Network Short
htonl() -- "Host to Network Long"
ntohs() -- "Network to Host Short"
ntohl() -- "Network to Host Long"

IP Addresses
socket01.utdallas.edu 129.110.43.11
sol2.utdallas.edu 129.110.34.2 etc
Other UTD machines for use socket02 – socket06 , sol1 , jupiter
Please do not use apache for Network programming

inet_addr() converts an IP address in numbers-and-dots notation into unsigned long
ina.sin_addr.s_addr = inet_addr(“129.110.43.11”) // Network byte order
Also can use inet_aton() -- “ascii to network”
int inet_aton(const char *cp,struct in_addr *inp);
inet_ntoa returns a string from a struct of type in_addr
inet_ntoa(ina.sin_addr) ;

Useful UNIX Commands
netstat –i prints information about the interfaces
netstat –ni prints this information using numeric addresses
loop back interface is called lo and the ethernet interface is called eth0 or le0 depending on the machine
netstat –r prints the routing table
netstat | grep PORT_NO shows the state of the client socket
ifconfig eth0 – Given the interface name ifconfig gives the details for each interface --- Ethernet Addr , inet_addr , Bcast , Mask , MTU
ping IP_addr -- Sends a packet to the host specified by IP_addr and prints out the roundtrip time ( Uses ICMP messages)
traceroute IP_addr -- Shows the path from this host to the destination printing out the roundtrip time for a packet to each hop in between
Tcpdump communicates directly with Data Link layer UDP Packet fail
System Calls
socket() – returns a socket descriptor
int socket(int domain, int type, int protocol);
bind() – What port I am on / what port to attach to
int bind(int sockfd, struct sockaddr *my_addr, int addrlen);
connect() – Connect to a remote host
int connect(int sockfd, struct sockaddr *serv_addr, int addrlen);
listen() – Waiting for someone to connect to my port
int listen(int sockfd, int backlog);
accept() – Get a file descriptor for a incomming connection
int accept(int sockfd, void *addr, int *addrlen);
send() and recv() – Send and receive data over a connection
int send(int sockfd, const void *msg, int len, int flags);
int recv(int sockfd, void *buf, int len, unsigned int flags);

sendto() and recvfrom() – Send and receive data without connection
int sendto(int sockfd, const void *msg, int len, unsigned int flags, const struct sockaddr *to, int tolen);
int recvfrom(int sockfd, void *buf, int len, unsigned int flags, struct sockaddr *from, int *fromlen);
close() and shutdown() – Close a connection Two way / One way
getpeername() – Obtain the peer name given the socket file descriptor
gethostname() – My computer name
int sock_get_port(const struct sockaddr *sockaddr,socklen_t addrlen);
Useful to get the port number given a struct of type sockaddr

Readn() writen() readline() Read / Write a particular number of bytes
Fork() – To start a new process with parents addr space
Exec() Load a new program on callers addr space



Issues in Client Programming
Identifying the Server.
Looking up a IP address.
Looking up a well known port name.
Specifying a local IP address.
UDP client design.
TCP client design.
Identifying the Server
Options:
hard-coded into the client program.
require that the user identify the server.
read from a configuration file.
use a separate protocol/network service to lookup the identity of the server.
Identifying a TCP/IP server.
Need an IP address, protocol and port.
We often use host names instead of IP addresses.
usually the protocol (UDP vs. TCP) is not specified by the user.
often the port is not specified by the user.
Services and Ports
Many services are available via “well known” addresses (names).
There is a mapping of service names to port numbers:
struct *servent getservbyname( char *service, char *protocol );
servent->s_port is the port number in network byte order.
Specifying a Local Address
When a client creates and binds a socket it must specify a local port and IP address.
Typically a client doesn’t care what port it is on:
haddr->port = htons(0);
Local IP address
A client can also ask the operating system to take care of specifying the local IP address:

haddr->sin_addr.s_addr=
htonl(INADDR_ANY);
UDP Client Design
Establish server address (IP and port).
Allocate a socket.
Specify that any valid local port and IP address can be used.
Communicate with server (send, recv)
Close the socket.
Connected mode UDP
A UDP client can call connect() to establish the address of the server.
The UDP client can then use read() and write() or send() and recv().
A UDP client using a connected mode socket can only talk to one server (using the connected-mode socket).
TCP Client Design
Establish server address (IP and port).
Allocate a socket.
Specify that any valid local port and IP address can be used.
Call connect()
Communicate with server (read,write).
Close the connection.
Closing a TCP socket
Many TCP based application protocols support multiple requests and/or variable length requests over a single TCP connection.
How does the server known when the client is done (and it is OK to close the socket) ?
Partial Close
One solution is for the client to shut down only it’s writing end of the socket.
The shutdown() system call provides this function.
shutdown( int s, int direction);
direction can be 0 to close the reading end or 1 to close the writing end.
shutdown sends info to the other process!
TCP sockets programming
Common problem areas:
null termination of strings.
reads don’t correspond to writes.
synchronization (including close()).
ambiguous protocol.
TCP Reads
Each call to read() on a TCP socket returns any available data (up to a maximum).
TCP buffers data at both ends of the connection.
You must be prepared to accept data 1 byte at a time from a TCP socket!
Server Design
Concurrent vs. Iterative
An iterative server handles a single client request at one time.
A concurrent server can handle multiple client requests at one time.
Concurrent vs. Iterative
Connectionless vs. Connection-Oriented
Statelessness
State: Information that a server maintains about the status of ongoing client interactions.
Connectionless servers that keep state information must be designed carefully!
The Dangers of Statefullness
Clients can go down at any time.
Client hosts can reboot many times.
The network can lose messages.
The network can duplicate messages.
Concurrent Server Design Alternatives
One child per client
Spawn one thread per client
Preforking multiple processes
Prethreaded Server
One child per client
Traditional Unix server:
TCP: after call to accept(), call fork().
UDP: after readfrom(), call fork().
Each process needs only a few sockets.
Small requests can be serviced in a small amount of time.
Parent process needs to clean up after children!!!! (call wait() ).
One thread per client
Almost like using fork() - just call pthread_create instead.
Using threads makes it easier (less overhead) to have sibling processes share information.
Sharing information must be done carefully (use pthread_mutex)
Prefork()’d Server
Creating a new process for each client is expensive.
We can create a bunch of processes, each of which can take care of a client.
Each child process is an iterative server.
Prefork()’d TCP Server
Initial process creates socket and binds to well known address.
Process now calls fork() a bunch of times.
All children call accept().
The next incoming connection will be handed to one child.
Preforking
As the book shows, having too many preforked children can be bad.
Using dynamic process allocation instead of a hard-coded number of children can avoid problems.
The parent process just manages the children, doesn’t worry about clients.

Sockets library vs. system call
A preforked TCP server won’t usually work the way we want if sockets is not part of the kernel:
calling accept() is a library call, not an atomic operation.
We can get around this by making sure only one child calls accept() at a time using some locking scheme.
Prethreaded Server
Same benefits as preforking.
Can also have the main thread do all the calls to accept() and hand off each client to an existing thread.
What’s the best server design for my application?
Many factors:
expected number of simultaneous clients.
Transaction size (time to compute or lookup the answer)
Variability in transaction size.
Available system resources (perhaps what resources can be required in order to run the service).
Server Design
It is important to understand the issues and options.
Knowledge of queuing theory can be a big help.
You might need to test a few alternatives to determine the best design.

unix network programs and computer networks

meant for MCA II year students Telangana university Nizamabad

/* Iterative TCP client */

#include "files.h"
main(int argc,char *argv[])
{
int sockfd;
struct sockaddr_in serv_addr;
pname=argv[0];
bzero((char *)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr(SERV_HOST_ADDRESS);
serv_addr.sin_port=htons(atoi(argv[1]));
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
perror("client:socket error");
if(connect(sockfd,(struct sockaddr*)&serv_addr,sizeof(serv_addr))<0)
{
perror("client:cant connect to error");
exit(1);
}
str_cli(stdin,sockfd);
close(sockfd);
exit(0);
}



/* Iterative TCP server program */
#include "file.h"
main(int argc,char *argv[])
{
int sockfd,newsockfd,clilen,childpid,i;
struct sockaddr_in cli_addr,serv_addr,peer;
pname=argv[0];
if((sockfd=socket(AF_INET,SOCK_STREAM,0))<0)
perror("server:cant open stream socket");
bzero((char *)&serv_addr,sizeof(serv_addr));
serv_addr.sin_family=AF_INET;
serv_addr.sin_addr.s_addr=inet_addr("172.16.0.1");
// serv_addr.sin_port=htons(SERV_TCP_PORT);
serv_addr.sin_port=htons(atoi(argv[1]));
if(bind(sockfd,(struct sockaddr *)&serv_addr,sizeof(serv_addr))<0)
{
perror("server:cant bind local address");
exit(1);
}
listen(sockfd,1);
// getsockname(sockfd,(struct sockaddr *) &peer,sizeof(peer));
// printf("\nIP= %s",inet_ntoa(peer.sin_addr.s_addr));
fflush(stdout);
for( i=0;i<6;++i)
{
printf("\nServer is waiting for a connection request::\n");
clilen=sizeof(cli_addr);
newsockfd=accept(sockfd,(struct sockaddr *)&cli_addr,&clilen);
if(newsockfd<0)
{
perror("server:accept error");
exit(1);
}
str_echo(newsockfd);
close(newsockfd);
}
printf("\nServer is exiting.....");
}