Linux Sockets

advertisement
Sockets Programming in Linux
References:
Internetworking with TCP/IP Vol III - Linux
version
UNIX Network Programming - W. Richard
Stevens
1
Sockets Programming in Linux
• Linux / UNIX Socket API functions
• Example TCP / UDP Clients
• Example TCP / UDP Servers
2
Basic Socket Functions
Server(Linux / UNIX)
• Create a socket of a particular type
– retcode = socket (family, type, protocol )
– s = socket (PF_INET, SOCK_STREAM, 0);
– returns socket number or -1 on error
• Bind that socket to a specific port
– retcode = bind (socket, localaddr, addrlen )
– n = bind (s, (struct sockaddr *)myaddr, sizeof(myaddr));
– returns 0 on success, -1 on fail
3
Basic Socket Functions
Server(Linux / UNIX)
• Wait for an incoming message
– retcode = listen (socket, queuelen)
– ans = listen(s, 0); /* queuelen max ~ 5*/
– return value 0 = success, -1 = fail
• Create a new socket and return new socket ID to client
– retcode = accept (socket, addr, addrlen)
– ans = accept (s, (struct sockaddr *)cl_addr, sizeof(cl_addr));
– return value socket number = success, -1 = fail
4
Basic Socket Functions
Server (Linux / UNIX)
• Read / send a message
–
–
–
–
–
–
–
–
retcode = read [write] (socket, buff, bufflen)
ans = read (s, buf, sizeof(buf));
ans = write (s, buf, strlen(buf));
return value word count = success, -1 = fail
retcode = recv [send] (socket, buff, bufflen, 0)
ans = recv (s, buf, sizeof(buf), 0);
ans = send (s, buf, strlen(buf), 0);
return value word count = success, -1 = fail
• Close the socket
– retcode = shutdown (socket , direction)
• direction: 0 means input, 1 means output, 2 means both
– retcode = close (socket );
– return value 0 = success, -1 = fail
5
Basic Socket Functions
Client (Linux / UNIX)
• Create a socket of a particular type
– Socket ( )
• Establish a connection to a remote Port/Socket
– retcode = connect (socket, addr, addrlen)
– ans = connect (s, (struct sockaddr *)&svr, sizeof(svr))
– return value 0 = success, -1 = fail
• Send and receive messages to/from remote socket
– Read( ) / Write( ) of recv( ) / send(
• Close the socket
– Close ( )
6
Additional Socket Functions
(Linux / UNIX)
• Byte ordering functions
– servaddr.sin_port = htons (SERV_PORT)
– myaddr.sin_addr.s_addr = htonl (INADDR_ANY)
• Name resolution functions
– host / protocol / service, by name / address / port
• Other Stuff
– zero out memory blocks
• bzero ((char *)&myaddr, sizeof(myaddr));
– copy memory blocks
• bcopy (hp->h_addr, (caddr_T)&svaddr.sin_addr, hp->h_length)
7
Example Linux Client
• Develop a set of procedures that can be used by
other programs to implement client / server.
int connectTCP (host, service)
int connectsock(host, service, “tcp”)
[identify service, host, port]
[get a socket]
[connect to service / host / port]
[return socket number]
8
Linux Client - Connectsock.c
int
connectTCP (char *host, char *service)
{
return connectsock (host, service, “tcp”);
}
9
Linux Client - Connectsock.c
#include <sys/types.h>, <sys/socket.h>,
<netinet/in.h>,<netdb.h>
int connectsock (char *host, char *service, char *protocol)
{
struct hostent
*phe;
struct servent
*pse;
struct protoent *ppe;
struct sockaddr_in
sin;
int
s, type;
10
Linux Client - Connectsock.c
bzero ((char *)&sin, sizeof (sin));
sin.sin_family = AF_INET;
if (pse = getservbyname (service, protocol) )
sin.sin_port = pse ->s_port;
else if ( (sin.sin_port = htons((u_short)atoi(service))) == 0)
error_exit (“can’t get %s service\n”, service);
if (phe = gethostbyname (host) )
bcopy(phe->h_addr, (char *)&sin.sin_addr, phe->h_length);
else if ((sin.sin_addr.s_addr = inet_addr(host)) == INADDR_NONE)
error_exit (“can’t get %s host\n”, host);
11
Linux Client - Connectsock.c
if ( (ppe = getprotobyname (protocol) == 0)
error_exit (“can’t get %s host\n”, host);
if (strcmp (protocol, “tcp”) == 0)
type = SOCK_STREAM;
else
type = SOCK_DGRAM;
if (s = socket (PF_INET, type, ppe->p_proto)) < 0)
error_exit (“Can’t create a socket\n”);
if (connect (s, (struct sockaddr *)&sin, sizeof(sin)) < 0)
error_exit (“can’t connect to remote socket\n”);
return s;
}
12
Example Linux Client - TCPecho.c
#include <stdio.h>
#define LINELEN
128
int main (argc, argv)
{
host = argv[1];
service = argv[2];
TCPecho (host, service);
exit (0);
}
13
Example Linux Client - TCPecho.c
int TCPecho (char *host, char *service)
{
char buf[LINELEN+1];
int s, n, outchars, inchars;
s = connectTCP (host, service);
while (fgets (buf, sizeof(buf), stdin))
{
buf[LINELEN] = ‘\0’;
outchars = strlen(buf);
(void) write (s, buf, outchars);
14
Example Linux Client - TCPecho.c
for (inchars = 0; inchars < outchars; inchars +=n)
{
n = read (s, &buf[inchars], outchars - inchars);
if (n < 0)
error_exit(“socket read failed\n”);
}
fputs (buf, stdout);
}
}
15
TCP Client Algorithm Issues
• Client / Server Communications
– request / response interaction
– write / read (send / recv)
• Single write may require multiple reads
– response may be segmented
– continue appending reads until return length = 0
16
Example Linux Client UDPecho.c
#include <stdio.h>
#define LINELEN 128
int main (argc, argv)
{
host = argv[1];
service = argv[2];
UDPecho (host, service);
exit (0);
}
17
Example Linux Client UDPecho.c
int UDPecho (char *host, char *service)
{
char
buf[LINELEN+1];
int s, n, outchars, inchars;
s = connectUDP (host, service);
while (fgets (buf, sizeof(buf), stdin))
{
buf[LINELEN] = ‘\0’;
outchars = strlen(buf);
(void) write (s, buf, outchars);
18
Example Linux Client UDPecho.c
if (read (s, buf, nchars) < 0)
error_exit (“Socket read failed \n”);
fputs (buf, stdout);
}
}
19
Iterative Connectionless Server
TIME Server
/* UDPtimed.c - main */
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <stdio.h>
#include <time.h>
#include <string.h>
extern int
errno;
int passiveUDP(const char *service);
int errexit(const char *format, ...);
#define UNIXEPOCH
2208988800 /* UNIX epoch, in secs*/
20
Iterative Connectionless Server
TIME Server
int main(int argc, char *argv[]) {
struct sockaddr_in fsin; /* the address of a client */
char * service = "time"; /* service name or port number */
char buf[1]; /* "input" buffer; any size > 0 */
int
sock;
/* server socket
*/
time_t now;
/* current time
*/
int
alen;
/* from-address length */
switch (argc) {
case 1:
break;
case 2:
service = argv[1];
break;
default:
errexit("usage: UDPtimed [port]\n");
}
21
Iterative Connectionless Server
TIME Server
sock = passiveUDP(service);
while (1) {
alen = sizeof(fsin);
if (recvfrom(sock, buf, sizeof(buf), 0,
(struct sockaddr *)&fsin, &alen) < 0)
errexit("recvfrom: %s\n", strerror(errno));
(void) time(&now);
now = htonl((u_long)(now + UNIXEPOCH));
(void) sendto(sock, (char *)&now, sizeof(now), 0,
(struct sockaddr *)&fsin, sizeof(fsin));
}
}
22
Concurrent Connection-Oriented
TCPechod.c
#include <sys/types.h, <sys/signal.h, <sys/socket.h, <sys/time.h,
<sys/resource.h, <sys/wait.h, <sys/errno.h, <netinet/in.h>,
<pthread.h>, <unistd.h>, <stdlib.h>, <stdio.h>, <string.h>, <errno.h>
#define QLEN
10
/* max connect queue length*/
#define BUFSIZE 4096
extern int
errno;
void * TCPechod(void *pfd);
int errexit(const char *format, ...);
int passiveTCP(const char *service, int qlen);
23
Concurrent Connection-Oriented
TCPechod.c
int main(int argc, char *argv[]) {
char *service = "echo"; /* service name/port #*/
struct sockaddr_in fsin;
/* address of client*/
unsigned int alen; /* len of client addr*/
int msock;
/* master server socket */
int ssock;
/* slave server socket */
pthread_t tid;
switch (argc) {
case 1:
break;
case 2:
service = argv[1];
break;
default: errexit("usage: TCPechod [port]\n");
}
24
Concurrent Connection-Oriented
TCPechod.c
msock = passiveTCP(service, QLEN);
while (1) {
alen = sizeof(fsin);
ssock = accept (msock, (struct sockaddr *)&fsin, &alen);
if (ssock < 0) {
errexit("accept: %s\n", strerror(errno));
}
//Now create a thread to handle client request
pthread_create (&tid, NULL, &TCPechod, (void *)&ssock);
} //end of while
}//end of main
25
Concurrent Connection-Oriented
TCPechod.c
msock = passiveTCP(service, QLEN);
while (1) {
alen = sizeof(fsin);
ssock = accept(msock, (struct sockaddr *)&fsin, &alen);
if (ssock < 0) {
errexit("accept: %s\n", strerror(errno));
}
//Now create a thread to handle client request
pthread_create (&tid, NULL, &TCPechod, (void *)&ssock);
} //end of while
}//end of main
26
Concurrent Connection-Oriented
TCPechod.c
void * TCPechod(void * pfd) {
char buf[BUFSIZE];
int cc, fd;
fd = * (int *) pfd;
while (cc = recv(fd, buf, sizeof (buf), 0)) {
if (cc < 0)
errexit("echo read: %s\n", strerror(errno));
printf ("We got: %s\n", buf);
if (send(fd, buf, cc, 0) < 0)
errexit("echo write: %s\n", strerror(errno));
bzero (&buf, sizeof(buf));
}
}
27
Summary
• Sockets API almost identical in Windows and
Linux
– Linux does not use WSAStartup, WSACleanup
– Linux uses close(socket), Windows uses
closesocket()
• Some differences in Operating System functions
– Multiple threads
• Windows - _beginthread (…)
• Linux – pthread_create (…)
– Multiple Processes
• Windows – CreateProcess(…)
• Linux – Fork()
28
Download