Elementary Socket System Calls

▪ Before exchanging data, 5-tuple must be specified in both the client and the server and stored in a socket.

{ protocol, local_addr, local_port_no, foreign_addr, foreign_port_no }

⇒ p.269 fig.6-8 (p.261 fig.6-2, p.262 fig.6-3 참조)

Case 1: server가 well-known process인 경우,

⇒ client는 이미 알고 있음.

Case 2: server가 user process인 경우,

⇒ client는 connect()를 하기 전에 미리 알고 있어야 함.

ex) p.284 "inet.h"

#define SERV_UDP_PORT 6000

#define SERV_TCP_PORT 6000

#define SERV_HOST_ADDR	"134.75.204.2"

Client PID

Server PID

<TCP/UDP Socket>

AF/PF =

IP Addr. =

Port No =

Buffer = "Message"

socket()

connect()

# netstat -a

<TCP/UDP Socket>

AF/PF =

IP Addr. =

Port No =

Buffer = "Message"

socket()

bind()

listen()

accept()

# netstat -a

TCP

UDP

TCP

UDP

IP

IP

IP Network

▪ socket()

- Specify the type of comm. protocol desired.

⇒ 사용하려는 protocol을 define하여 comm. I/O 자료구조(socket)를 만듬.

#include <sys/types.h>

#include <sys/socket.h>

int socket (int family,	int type,       int protocol);

AF_UNIX	SOCK_STREAM	(TCP)	typically 0

AF_INET	SOCK_DGRAM	(UDP)	(p.268 fig.6-7 참조)

AF_NS	SOCK_RAW	(IP)

AF_IMPLINK	SOCK_SEQPACKET(AF_NS)

SOCK_RDM	(not implemented)

returns a s.d. (similar to a f.d.)	(p.268 fig.6-6 참조)

ex) p.76 fig.2-13

- s.d = f.d. (in file descriptor table)

- The process or process group receives the SIGIO, SIGURG signals for the socket when the msg. is arrived.

▪ bind(): for a server

- After generating s.d., a server fills in the local_addr and local_port_no.

⇒ A server registers its addr. and port no. into the comm. module, and later send() & recv() just use a s.d. to exchange data.

#include <sys/types.h>

#include <sys/socket.h>

int bind (int sd, struct sockaddr *myaddr, int addrlen);

a ptr. to a protocol	the size of the

-specific addr.	addr. structure

<netinet/in.h>에 (u_long) 0X00000000로 define

ex) p.285	⇒ system이 자신의 addr.를 fill-in ⇒ no error

⇒ bind()전에 myaddr을 fill-in.	byte ordering routines

serv_addr.sin_addr.s_addr = htonl (INADDR_ANY); /* host-to-network long */

serv_addr.sin_port = htons (SERV_TCP_PORT);   /* host-to network short */

▪ listen(): for a server

- Used by a connection-oriented server to indicate how many connection requests can be "queued" by the system.

⇒ It is possible for additional connection requests to arrive from other clients while the server fork() a child process and then have the parent process execute another accept().

int listen (int sd, int backlog);

usually 5, the ‘max. value’ currently allowed

▪ accept(): for a server

- An actual connection from some client process is waited by accept().

- accept() takes the first connection request on the queue and creates "another" socket with the "same" properties as the original.

- If there are NO connection requests pending, this call "blocks" the caller until one arrives.

int accept (int sd, struct sockaddr *peer, int addrlen);

a new s.d.	the addr. of the client    the actual no. of bytes that the system	call stores in the peer arg. (=16 byte

for Internet, p.266 fig.6-5 except unused)

ex) concurrent server (p.76 fig.2-13 참조)

close (new f.d) & f.d. 사용 /* parent */

close (f.d) & new f.d. 사용 /* child  */

socket structure

a process ID or a process group ID for the delivery of SIGIO, SIGURG signals

ㄴ.d.

new s.d.

so_pgrp

{protocol,

source port no.

source IP addr.

dest. port no.

dest. IP addr. }

so_pgrp

{protocol,

source port no.

source IP addr.

dest. port no.

dest. IP addr. }

s.d.

new s.d.

fork()

s.d.

- two kinds of servers

① ‘concurrent’ server: the child process services the connection using the connected s.d., a ‘new’ s.d., and the parent process waits for another connection request using the ‘original’ s.d.

ex) typical scenario: p.273

p.284 TCP server

② ‘iterative’ server: the server handles the request using the connected s.d., a ‘new’ s.d. It then terminates the connection with a close() and waits for another connection using the ‘original’ s.d.

ex) typical scenario: p.274

▪ connect(): for a client

- Establish a connection with a server.

⇒ 3-way handshake

#include <sys/types.h>

#include <sys/socket.h>

int connect (int sd, struct sockaddr *servaddr, int addrlen);

a ptr. to a server's	the size of the

socket addr.	addr. structure

ex) p.286

⇒ connect() 전에 servaddr를 fill-in.

serv_addr.sin_addr.s_addr = htonl (SERV_HOST_ADDR);

serv_addr.sin_port = htons (SERV_TCP_PORT);

; client의 addr.는 TCP module이 이미 알고 있음.

client의 port no.는 ephemeral port no.임.

▪ connect() → accept() 후,

3-way handshaking이 수행되고, 5-tuple을 client와 server가 모두 알고 있게 됨.

{ protocol, local_addr, local_port_no, foreign_addr, foreign_port_no }

ex)	p.284 TCP server & client

p.286 UDP server & client

▪ send() ↔ recv(), sendto() ↔ recvfrom(), write() ↔ read()

- returns the length of the data that was written or read: p.274 참조

- flags: usually 0. ORing is possible.

․ MSG_OOB: send or receive out-of-band data.

⇒ urgent data: send this data "before" any other data that it has buffered.

․ MSG_PEEK: do NOT discard the data after recv()/recvfrom() returns.

ex) section 6.14

․ MSG_DONTROUTE: The outgoing msg. is to bypass the normal routing	mechanisms.

⇒ Instead, the msg. is "directed" to the appropriate network interface (network gateway), as specified by the “network portion” of the dest. addr.

⇒ send()/sendto()에서 사용. gateway로 직접 보냄.

ex) section 6.11, p.318

▪ close()

- Close a socket.

int close(int sd);

- Normally, the system returns from close() immediately, but the kernel still tries to send any data already queued.

Functions

▪ Byte ordering routines

- Handles the "potential" byte order differences bet. computer architectures and different network protocols.

u_long htonl (u_long hostlong);	/* host byte order → network byte order */

/* long integer: IP address */

u_short htons (u_short hostshort);	/* host byte order → network byte order */

/* short integer: port no. */

u_long ntohl (u_long netlong);

u_short ntohs (u_short netshort);

- Byte order

How to store 16-bit integer into 2 bytes?

① little endian: store the low order byte at the starting addr.

send data

byte 0 byte 1 byte 2 byte 3 …

ex) Intel 80XXX, DEC VAX 등

0	byte 0	byte 1
2	byte 2	byte 3
	…
i	byte i	byte i+1
	…

② big endian: store the high-order byte at the starting addr.

byte 1 byte 0 byte 3 byte 2 …

send data

ex) IBM 370, MC68000 등

0	byte 1	byte 0
2	byte 3	byte 2
	…
i	byte i+1	byte i
	…

⇒ A network protocol specifies its network byte order.

ex) TCP/IP, XNS (Xerox), SNA(IBM): the big endian format.

▪ Byte operations

- Manipulate the standard C char. strings.

ex) strcpy(), strcmp() 등.

- 4.3 BSD defines the three routines that operate on ‘user-defined’ byte strings. (not the standard C char. strings)

⇒ No '\0' at the end.

⇒ Instead specify the length of the string (nbytes) as an argument to the function.

int bcopy (char *src, char *dest, int nbytes);	/* copy src → dest */

int bzero (char *dest, int nbytes);	/* writes null bytes */

int bcmp (char *ptr1, char *ptr2, int nbytes);	/* compare two strings */

0: if identical,

nonzero; otherwise

▪ Addr. conversion routines

- Converts bet. the dotted-decimal format (char. string) and 32-bit integer.

unsigned long inet_addr (char* ptr);	/* char. string →

32-bit Internet addr. */

char* inet_ntoa (struct in_addr inaddr);	/* 32-bit Internet addr. →

char. string*/

Examples: a Client and a Server

▪ TCP server	p.284

client  p.286

▪ UDP server p.287

client  p.288

▪ utility routines: readn(), writen(), readline(), writeline(),

str_echo(), str_cli(), dg_echo(), dg_cli()

⇒ an echo program: server가 client의 input string을 echo하여 줌.

▪ Java Examples

- A server & a client using TCP: Server가 1에서 10까지의 정수를 Client에 보내면 Client는 이 데이터를 받아서 출력함.

//------------------------------------------------

// A TCP Server: Send 10 integers to a client

// # java ServerSide server_port_no &

//------------------------------------------------

import java.io.*;

import java.net.*;

class ServerSide{

public static void main(String args[]){

try{

int END=10;

int port=Integer.parseInt(args[0]);

// InetAddress 클래스의 static method들을 사용함.

InetAddress sa=InetAddress.getLocalHost();

// Print the IP address, Host name and port no. of a server.

String saddr=sa.getHostAddress();

System.out.println("\nAddress of a server: "+saddr);

String sname=sa.getHostName();

System.out.println("Name of a server: "+sname);

// ServerSocket 객체 s1을 생성함.

ServerSocket s1=new ServerSocket(port);

int sport=s1.getLocalPort();

System.out.println("Port no of a server: "+sport);

while(true){

// Client의 요청이 발생하면 ServerSocket의 메소드를 사용하여

// 새로운 Socket 객체를 생성함.

Socket s2=s1.accept();

// 새로운 Socket 클래스의 메소드를 사용하여 InetAddress 객체를 생성함.

InetAddress ca=s2.getInetAddress();

// Print the IP address, Host name and port no. of a connected client.

String caddr=ca.getHostAddress();

System.out.println("Address of a client: "+caddr);

String cname=ca.getHostName();

System.out.println("Name of a client: "+cname);

int cport=s2.getPort();

System.out.println("Port no of a client: "+cport);

// 데이터를 출력하기 위해 Socket 객체로부터 OutputStream 객체를 생성함.

OutputStream os=s2.getOutputStream();

DataOutputStream dos=new DataOutputStream(os);

for(int i=1;i<=END;i++){

// DataOutputStream 객체의 writeInt 메소드를 사용하여 정수를 출력.

dos.writeInt(i);

System.out.println("Send to a client: "+i);

}

s2.close();

}

}

catch(Exception e){

System.out.println("Exception: "+e);

}

} // End of main.

} // End of class

//------------------------------------------------

// A TCP client: Receive & print 10 integers from a server

// # java ClientSide server_IP_addr server_port_no

//------------------------------------------------

import java.io.*;

import java.net.*;

class ClientSide{

public static void main(String args[]){

try{

String server=args[0];

int port=Integer.parseInt(args[1]);

// 지정된 IP addr.와 port no.를 사용하여 Socket 객체를 생성함.

Socket c=new Socket(server, port);

// 데이터를 입력하기 위해 Socket 객체로부터 InputStream 객체를 생성함.

InputStream is=c.getInputStream();

DataInputStream dis=new DataInputStream(is);

for(int i=1;i<=10;i++){

// DataInputStream 객체의 readInt 메소드를 사용하여 정수를 입력.

int j=dis.readInt();

System.out.println("Received from a server: "+j);

}

c.close();

}

catch(Exception e){

System.out.println("Exception: "+e);

}

} // End of main.

} // End of class

* javac and java PATH 설정 (In .cshrc);

set path=( . /usr/bin, ……, /opt/jdk1-3/j2sdk1_3_0/bin)

Multi-threaded Server: I/O Multiplexing

▪ Single-threaded server: 하나의 socket에 연결됨.

C

S

▪ Multi-threaded server: 여러 개의 socket을 관리함.

Cn

C2

S

C1

.

.

.

▪ Multiplexing: For a process that reads input from more than one socket.

ex) A line printer spooler: two sockets.

① print requests on the same host: a unix stream socket.

(Unix domain protocol)

② print requests on other hosts: a TCP socket.

ex) a chatting server (컴퓨터 네트워크 프로그래밍, p.104 fig.4-2)

chat_server

0  1  2	511

......

client_s[ ]

s

TCP module

new req.

.

.

.

user 1

user 2

user 512

s: 초기 socket

client_s[ ]: chatting

참가자들의 socket array

▪ Problem

- A spooler starts accept()/read() on only "one" socket.

⇒ It could "block" while waiting for a req. on that socket, and in the meantime a req. can arrive on the other socket.

⇒ It can NOT process the req. from the other socket.

- How to 'multiplexing' different I/O channels?

select(): Allows a user process to instruct the kernel to wait for "any one" of multiple inputs to occur, and to wake up the process only when "one of these" inputs occurs.

ex) 컴퓨터 네트워크 프로그래밍, p.103 fig.4-1

모든 socket의 I/O 감지

socket()
bind()
select()
Y(chatting 참가 req.)	N(chatting msg. 수신)
초기 socket?
accept()	chatting msg. 방송
client_s[ ]에 새로운 socket 추가

▪ select() (p.329)

#include <sys/types.h>

#include <sys/time.h>

int select (int maxfdp1, fd_set *readfds, fd_set *writefds, fd_set *exceptfds,

struct timeval *timeout);

① maxfdp1: the "no." of f.d.s to be tested.	⇒ the max. f.d. to be tested + 1

ex) the descriptors 0, 1, 2, ～ , (maxfdp1-1) are tested.

② 1-bit arrays	currently max.=256

각각의 I/O 변화가 발생하였을 때, 이를 감지할 대상을 ‘1’로 지정하는 배열형 구조체

	0	1	2	3		maxfdp1-1
readfds	1	0	0	1	……			읽기
	0	1	2	3		maxfdp1-1
writefds	0	1	0	1	……			쓰기
	0	1	2	3		maxfdp1-1
exceptfds	0	0	0	0	……			예외상황

③ struct timeval {

long tv_sec;

long tv_usec;

}

case 1: timeval = 0

return immediately after checking the f.d.s - do "not" wait.

(각각의 I/O 변화를 check한 후 즉시 return함)

case 2: timeval > 0

return after waiting for a "fixed amount" of time.

(일정한 시간동안 I/O를 기다리다가 return함)

case 3: timeval = NULL

wait "infinitely".

(어느 하나의 I/O가 일어날 때까지 무한정으로 가다림)

ex) (struct timeval *) 0	; NULL(보통의 경우)

▪ FD_XXX macros

- For manipulating f.d. sets. (readfds, writefds, exceptfds)

FD_ZERO (fd_set *fdset);	/* clear all bits in fdset.	*/

FD_SET (int fd, fd_set *fdset); /* turn the bit for position fd on(1) in fdset. */

bit position	(test할 socket을 지정함)

FD_CLR (int fd, fd_set *fdset); /* turn the bit for position fd off(0) in fdset. */

(socket을 test하지 않음)

FD_ISSET (int fd, fd_set *fdset);  /* test the bit for position fd in fdset */

(해당 bit가 set되어 있는지를 검사 -

해당 bit가 set되어 있으면 1을 return)

ex)

fd_set read_fds;

…

FD_ZERO (&read_fds);	/* initialize the set - all bits are cleared */

FD_SET (1, &read_fds);	/* turn the bit for readfds 1 */

FD_SET (4, &read_fds);	/* turn the bit for readfds 4 */

select (maxfdp1, &read_fds, (fd_set *) 0, (fd_set *) 0, (struct timeval *) 0);

NULL

⇒ tell us if any of the f.d. in the set {1, 4} are ready for reading.

(1, 4번 socket에 입력 msg.가 들어오기를 무한정 기다렸다가, 어느 한 쪽의 msg.가 도착하면 return함)

⇒ 대개는 특정 f.d. position을 지정하기보다는 accept()에서 return된 new socket 값들을 저장했다가 select()에서 사용함.

ex) 컴퓨터 네트워크 프로그래밍, p.110 chat_server.c (chatting server)

▪ Internet Superserver

- The Internet daemon (inetd) is started at boot time from an initialization file such as /etc/rc.

- When it is started, inetd reads its config. file from /etc/inetd.conf.

⇒ contains the names of the services that inetd listens for and "starts".

⇒ On startup, it reads the /etc/inetd.conf file and creates a socket on the appropriate type (TCP or UDP) for all the services specified in the file.

ex) p.335 fig.6-17

- Then, select() is executed to wait for the first socket to arrive a request.

- inetd fork()s and the child process handles the service request.

ex) p.336 fig.6-18

▪ Web servers

- HTTPd(NCSA), Apache Server, IIS(MS) 등

- CGI(Common Gateway Interface): Web server ↔ DB server 연결 process 생성

▪ WAS servers (Web Application Server)

- 웹에서 사용되는 컴포넌트들을 올려놓고 사용하게 되는 서버

e.g., EJB의 bean들

- 실제로 처리해야 하는 ‘비즈니스 로직’들이 올라가서 웹 서버로 들어오는 요청을 처리해서 돌려 줌.

- middleware 필요.

Other Sockets

▪ Windows socket

- Windows 3.1, Windows 95/98, Windows NT, Windows 2000/XP 등을 포함한 모든 MS Windows OS에서 TCP/IP protocol을 사용할 수 있는 표준 API를 제공.

- Berkeley socket을 확장: Berkeley socket의 대부분을 수용하며, Windows 특성에 맞게 몇 개의 함수가 추가되었음.

ex) Winsock 1.1, 2.0 등

▪ Java, Delphi 등