You are on page 1of 45

Chuyên đề tin

Lập trình mạng


P2: Lập trình Socket

Khoa Toán tin ứng dụng

NTV 1
Nội dung

 Socket
 TCP Socket
 UDP Socket
 Cài đặt

NTV 2
Socket

NTV 3
Lịch sử

 Đầu những năm 1980:


 ARPA hỗ trợ ĐH Caliornia Berkeley để
chuyển các phần mềm TCP/IP sang HĐH
UNIX
 Một phần dự án: xây dựng API => socket
API (BSD socket)
 Windows: Microsoft chọn socket làm API
phát triển ứng dụng mạng
 Socket là chuẩn công nghiệp được hỗ trợ
phổ biến

NTV 4
Thiết kế

 Socket xác định các hàm hỗ trợ giao tiếp


mạng chung thay vì gắn với một bộ giao
thức cụ thể
 Socket cung cấp API ở tầng transport
 Truyền thông bằng socket độc lập với ngôn
ngữ lập trình
 Truyền thông với socket giống như đọc/ghi
file (file I/O)

NTV 5
Cách nhìn

 Với HĐH
 giao tiếp truyền thông
 Cài đặt giao thức
 Với ứng dụng
 Giao tiếp truyền thông mạng
 Đọc/ghi socket (tương tự như đọc ghi file)

NTV 6
 WindowsNT

NTV 7
Truyền thông với socket

 Quá trình
host or host or
server server

controlled by
app developer
process process

socket socket
TCP with TCP with
buffers, Internet buffers,
variables variables

controlled
by OS

NTV 8
 Server: nghe/chờ

Connection request
port

server
Client

NTV 9
 Truyền thông: server mở port khác và trao
đổi
 tại sao mở port khác
port

server

port
Client
port Connection

NTV 10
Socket descriptor

descriptor table

0: a pointer to internal data


structure for file 0
family: AF_INET
1: a pointer to internal data
structure for file 1
service: SOCK_STREAM
2:
a pointer to internal data
structure for file 2
protocol: TCP
3: a pointer to internal data
structure for file 3
local IP:
4: remote IP:
local Port:
remote Port:

NTV 11
TCP socket

NTV 12
Sơ đồ TCP server

socket()

TCP client bind()


socket()
listen()

Connection
request accept()
connect()

data (request)
write() read()

Process request Wait next


request
data (reply)
read() write()

EOF
close() read()

close()

NTV 13
socket() : Create a socket

#include <sys/socket.h>
int socket (int family, int type, int protocol);
Returns: non-negative descriptor if OK, -1 on error

 family = address family


 AF_INET (TCP/IP)
 AF_INET6
 type = socket type
 SOCK_STREAM (TCP)
 SOCK_DGRAM (UDP)
 protocol
 0 for system’s default
 Specified for SOCK_RAW (IP) sockets

NTV 14
bind() : Assign an address to a socket

#include <sys/socket.h>
int bind (int sockfd, const struct sockaddr *sockaddr, socklen_t addrlen);

Returns: 0 if OK,-1 on error

 sockfd = file descriptor for created socket


 sockaddr = a pointer to a structure of socket address
 addrlen = the size of address

NTV 15
listen() : Indicate that the socket will accept
connections

#include <sys/socket.h>
int listen (int sockfd, int backlog);

Returns: 0 if OK, -1 on error

 sockfd = file descriptor for created socket


 backlog = the maximum number of queuing connections

NTV 16
accept (): Blocks waiting for a connection

#include <sys/socket.h>
int accept (int sockfd, struct sockaddr *cliaddr, socklen_t *addrlen);

Returns: non-negative descriptor if OK, -1 on error

 sockfd = file descriptor for created socket


 cliaddr = a pointer to a socket address
structure of the connected peer process
 addrlen = the size of the address structure

NTV 17
Server

accept

Completed
connection queue
Three way
handshake
TCP complete

Incomplete
connection queue

NTV 18
connect(): Establish a connection with a TCP
server

#include <sys/socket.h>
int connect (int sockfd, const struct sockaddr *servaddr, socklen_t addrlen);

Returns: 0 if OK, -1 on error

sockfd = file descriptor for created socket


servaddr = a pointer to a socket address structure of
connecting server
addrlen = the size of the address structure

NTV 19
Socket I/O: read()

int newfd; /* socket descriptor */


char buf[512]; /* used by read() */
int nbytes; /* used by read() */

/* 1) create the socket */


/* 2) bind the socket to a port */
/* 3) listen on the socket */
/* 4) accept the incoming connection */

if((nbytes = read(newfd, buf, sizeof(buf))) < 0) {


perror(“read”); exit(1);
}

NTV 20
Socket I/O: write()

int fd; /* socket descriptor */


struct sockaddr_in srv; /* used by connect() */
char buf[512]; /* used by write() */
int nbytes; /* used by write() */

/* 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);
}

NTV 21
close(): giải phóng tài nguyên

#include <sys/socket.h>
int close (int sockfd);

Returns: 0 if OK, -1 on error

sockfd = file descriptor for created socket

NTV 22
TCP Client/Server Example: echo

1. The client reads a line of text from its standard input and
writes the line to the server.
2. The server reads the line from its network input and echoes
the line back to the client.
3. The client reads the echoed line and prints it on its standard
output.

fgets write read


TCP TCP
Client Server
fputs read write

Usage:
%server <listen port>
%client <server’s IP address> <server’s listen port number>

NTV 23
Biến đổi trạng thái
BEGIN/socket()
CLOSED Client Active Open connect()
send SYN
Server Passive Open
bind(),listen(),accept() Close()

rcv SYN LISTEN Active Open


send SYN,ACK send SYN
rcv RST Close()
SYN RCVD rcv SYN SYN SENT
send SYN,ACK
rcv ACK of SYN
Close()
send FIN Close() send FIN ESTABLISHED rcv SYN,ACK
send ACK
rcv FIN
FIN WAIT-1 send ACK rcv FIN CLOSE_WAIT
send ACK
rcv ACK rcv FIN,ACK CLOSING Close()
send ACK send FIN
rcv ACK rcv ACK
FIN WAIT-2 LAST_ACK
rcv FIN TIME_WAIT timer ~ 1 min
send ACK

NTV 24
TCP Server
socket()

bind()

TCP Client listen()

socket() accept()
connection establishment
connect()

data request read()


write()

data reply write()


read()

close() end-of-file notification read()

close()

NTV 25
UDP Socket

NTV 26
Sequence
UDP Server
socket()

bind()
UDP Client
recvfrom()
socket()
blocks until datagram
sendto() received from a client
data request

data reply sendto()


recvfrom()

close()

NTV 27
socket() : Create a socket

#include <sys/socket.h>
int socket (int family, int type, int protocol);
Returns: non-negative descriptor if OK, -1 on error

 family = address family


 AF_INET (TCP/IP)
 AF_INET6
 type = socket type
 SOCK_DGRAM (UDP)
 protocol
 0 for system’s default
 Specified for SOCK_RAW (IP) sockets

NTV 28
int fd; /* socket descriptor */

if((fd = socket(AF_INET, SOCK_DGRAM, 0)) < 0) {


perror(“socket”);
exit(1);
}

NTV 29
bind(): Assign addr & port

int fd; /* socket descriptor */


struct sockaddr_in servaddr; /* used by bind() */

/* create the socket */

servaddr.sin_family = AF_INET; // use the Internet address family

/* bind: socket ‘fd’ to port 80*/


servaddr.sin_port = htons(80);

/* bind: a client may connect to any of my addresses */


servaddr.sin_addr.s_addr = htonl(INADDR_ANY);

if(bind(fd, (struct sockaddr*) &servaddr, sizeof(servaddr)) < 0) {


perror("bind"); exit(1);
}

NTV 30
sento(): send UDP datagram

#include <sys/socket.h>

ssize_t sendto(int sockfd, const void *buff, size_t nbytes, int flags,
const struct sockaddr *to, socklen_t addrlen);

 sockfd = socket descriptor


 buff = a pointer to a buffer to read into or write from
 nbytes = number of bytes to read or write
 flags = for I/O functions (should be 0)
 to = a pointer to socket address structure containing protocol
address of where to send the data
 addrlen = the size of socket address structure

NTV 31
int fd; /* socket descriptor */
struct sockaddr_in srv; /* used by sendto() */

/* 1) create the socket */

/* sendto: send data to IP Address “128.2.35.50” port 80 */


srv.sin_family = AF_INET;
srv.sin_port = htons(80);
srv.sin_addr.s_addr = inet_addr(“128.2.35.50”);

nbytes = sendto(fd, buf, sizeof(buf), 0 /* flags */,


(struct sockaddr*) &srv, sizeof(srv));
if(nbytes < 0) {
perror(“sendto”); exit(1);
}

NTV 32
recvfrom(): receive UDP Datagram

#include <sys/socket.h>

ssize_t recvfrom(int sockfd, void *buff, size_t nbytes, int flags,


struct sockaddr *from, socklen_t *addrlen);

 sockfd = socket descriptor


 buff = a pointer to a buffer to read into or write from
 nbytes = number of bytes to read or write
 flags = for I/O functions (should be 0)
 from = a pointer to socket address structure containing
protocol address of who sent the data
 addrlen = the size of socket address structure

NTV 33
int fd; /* socket descriptor */
struct sockaddr_in servaddr; /* used by bind() */
struct sockaddr_in cliaddr; /* used by recvfrom() */
char buf[512]; /* used by recvfrom() */
int cliaddr_len = sizeof(cliaddr); //used by recvfrom()
int nbytes; /* used by recvfrom() */

/* 1) create the socket */


/* 2) bind to the socket */

nbytes = recvfrom(fd, buf, sizeof(buf), 0 /* flags */,


(struct sockaddr*) &cliaddr, &cliaddr_len);
if(nbytes < 0) {
perror(“recvfrom”); exit(1);
}

NTV 34
close(): giải phóng tài nguyên

#include <sys/socket.h>
int close (int sockfd);

Returns: 0 if OK, -1 on error

sockfd = file descriptor for created socket

NTV 35
Ví dụ

 For example: NTP


daemon
NTP
daemon

Port 123  What does a UDP server need to


do so that a UDP client can
connect to it?
UDP

IP

Ethernet Adapter

NTV 36
So sánh UDP và TCP socket

TCP Server
socket()

bind() UDP Server


socket()
TCP Client listen() bind()
UDP Client
socket() accept() recvfrom()
socket()
connection establishment blocks until datagram
connect() received from a client
sendto() data request
data request read()
write()

data reply write() data reply sendto()


read() recvfrom()

close()
close() end-of-file notificationread()
close()

NTV 37
Cài đặt

NTV 38
 Cài đặt phụ thuộc
 HĐH
 Ngôn ngữ lập trình hỗ trợ
 C, C++: winsock
 Java: socket package
 Vấn đề cài đặt
 Cần xử lý nhiều request đồng thời

NTV 39
 TÀI LIỆU THAM KHẢO
 Patrice, Bonner - Network Programming with Windows Sockets – Prentice Hall – 1995
 Anthony Jones and Jim Ohlund - Network Programming for Microsoft Windows – Microsoft - 1999.
 Java Network Programming, 3rd Edition – O Reilly
 Jonathan B. Postel - rfc821 (SMTP) Simple Mail Transfer Protocol – Internet - 1982.
 David H. Crocker - rfc822 Standard for the format of ARPA Internet text messages – Internet - 1982.
 Marshall Rose - rfc1081 (POP3) Post Office Protocol Version 3 – Internet - 1988.
 Marshall Rose - rfc1082 Post Office Protocol - Version 3, Extended Service Offerings – Internet – 1988.
 Nathaniel S. Borenstein, Ned Freed, Gregory M. Vaudreuil - rfc1521 MIME (Multipurpose Internet Mail
Extensions) Part One – Internet - 1993.
 J. Klensin, M. Rose, E. Stefferud, D. Crocker - rfc1651 SMTP Service Extensions – Internet - 1994.
 N. Freed, N. Borenstein - rfc2045 - Multipurpose Internet Mail Extensions (MIME) Part One – Internet
– 1996.
 Network Programming with Windows Sockets – Prentice Hall
 Anthony Jones and Jim Ohlund - Network Programming for Microsoft Windows – Microsoft.
 rfc821 - (SMTP) Simple Mail Transfer Protocol.
 rfc822 - Standard for the format of ARPA Internet text messages.
 rfc1081 - (POP3) Post Office Protocol Version 3.
 rfc1082 - Post Office Protocol - Version 3, Extended Service Offerings.
 rfc1521 - MIME (Multipurpose Internet Mail Extensions) Part One.
 rfc1651 - SMTP Service Extensions.
 rfc2045 - Multipurpose Internet Mail Extensions (MIME) Part One.

NTV 40
Địa chỉ IP
 IP Addresses are commonly written as strings (“128.2.35.50”), but
programs deal with IP addresses as integers.
Converting strings to numerical address:
#include <arpa/inet.h>
int inet_aton(const char *strptr, struct in_addr *addrptr);

Returns: 1 if string was valid, 0 on error

in_addr_t inet_addr(const char *strptr);

Returns: 32-bit binary network byte ordered IPv4 address;

INADDR_NONE if error
Converting a numerical address to a string:
char *inet_ntoa(struct in_addr inaddr);

Returns: pointer to dotted-decimal string

NTV 41
Echo server: main
int main(int argc, char **argv) {
int listenfd, connfd; // socket descriptor
int listenport, clientport; // listen port number and client’s port number
struct sockaddr_in cliaddr; // a structure of client’s address
int cliaddrlen; // the size of client’s address structure
char cliaddr_str[INET_ADDRSTRLEN];

listenport = atoi(argv[1]); /* Get listen port number from program argument*/


listenfd = Open_listenfd(port);
while (1) {
clientlen = sizeof(clientaddr);
connfd = accept(listenfd, (struct sockaddr *)&clientaddr, &clientlen);
inet_ntop (AF_INET, &cliaddr.sin_addr, cliaddr_str, sizeof (cliaddr_str));
clientport = ntohs(cliaddr.sin_port);
printf(“Rereived a connection form %s (%s)\n", cliaddr_str, clientport);
echo(connfd);
close(connfd);
}
}

NTV 42
Echo Server: Open_listenfd
int Open_listenfd(int port)
{
int listenfd;
struct sockaddr_in servaddr;

if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) // create a socket


return -1;
bzero((char *) &serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);
if (bind(listenfd, (struct sockaddr *)&serveraddr, sizeof(serveraddr)) < 0)
return -1;

if (listen(listenfd, LISTENQ) < 0) // Make it a listening socket


return -1;
return listenfd;
}

NTV 43
Echo client: main
int main(int argc, char **argv)
{
int clientfd, servport;
char *servaddr_str, buf[MAXLINE];
int n;
servaddr_str = argv[1];
servport = atoi(argv[2]);

clientfd = Open_clientfd(servaddr_str, servport);

while (fgets(buf, MAXLINE, stdin) != NULL) {


write (clientfd, buf, strlen(buf));
read (clientfd, buf, MAXLINE)
fputs (buf, stdout);
}
close(clientfd);
exit(0);
}

NTV 44
Echo Client: Open_clientfd
int Open_clientfd(char *servaddr_str, int servport)
{
int clientfd;
struct sockaddr_in servaddr;

if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)


return -1; /* check errno for cause of error */

bzero((char *) &servaddr, sizeof (servaddr));


servaddr.sin_family = AF_INET;
if ( inet_pton(AF_INET, servaddr_str, &servaddr.sin_addr) <= 0)
err_sys("inet_pton error");
serveraddr.sin_port = htons (servport);

/* Establish a connection with the server */


if (connect(clientfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0)
return -1;
return clientfd;
}

NTV 45

You might also like