網路程式設計 - socket 程式設計

47
網網網網網網 網網網網網網 - - Socket Socket 網網網網 網網網網 網網網 網網網 [email protected] [email protected]

Upload: nat

Post on 26-Jan-2016

145 views

Category:

Documents


9 download

DESCRIPTION

網路程式設計 - Socket 程式設計. 蔡進義 [email protected]. 大綱. TCP/IP 協定複習 什麼是 Socket Socket API 的使用 Socket 相関資料的結構 常用 Socket API. TCP / IP 協定 複習. FTP , SMTP , Telnet , DNS , SNMP. What is TCP / IP Transmission Control Protocol / Internet Protocol. TCP , UDP. 應用層. Application. - PowerPoint PPT Presentation

TRANSCRIPT

Page 1: 網路程式設計 - Socket 程式設計

網路程式設計網路程式設計 --SocketSocket 程式設計程式設計

蔡進義 蔡進義 [email protected] [email protected]

Page 2: 網路程式設計 - Socket 程式設計

22

大綱大綱 TCP/IP 協定複習

什麼是 Socket

Socket API 的使用

Socket 相関資料的結構

常用 Socket API

Page 3: 網路程式設計 - Socket 程式設計

33

TCP / IPTCP / IP 協定協定複習複習 What is TCP / IP What is TCP / IP Transmission Control Protocol / Internet Protocol Transmission Control Protocol / Internet Protocol

網路存取層網路存取層

網路層網路層

傳輸層傳輸層

應用層應用層

Network Access Network Access

Network Network

Transport Transport

Application Application

FTP , SMTP , Telnet , DNS , SNMP

TCP , UDP

IP , ARP

Ethernet , FDDI , Token Ring

Page 4: 網路程式設計 - Socket 程式設計

44

Port(Port( 埠埠 ) ) 每一台主機有每一台主機有 6553665536 個個 portsports

• port 0 ~ port 65535port 0 ~ port 65535

一些保留的一些保留的 portsports• 20, 21: FTP20, 21: FTP• 23: Telnet23: Telnet• 80: HTTP80: HTTP

未保留未保留• 1024 ~ 50001024 ~ 5000

Port 1

Port 2

Port 65535

Port 0

Port 3

Port 3333 Port 3333

Port 80 Port 80

Page 5: 網路程式設計 - Socket 程式設計

55

大綱大綱 TCP/IPTCP/IP 協定複習協定複習

什麼是什麼是 SocketSocket

Socket APISocket API 的使用 的使用

SocketSocket 相関資料的結構 相関資料的結構

常用常用 Socket API Socket API

Page 6: 網路程式設計 - Socket 程式設計

66

什麼是什麼是 SocketSocket ?? SocketSocket 首次出現在首次出現在 Berkeley UNIXBerkeley UNIX 中,作為網路設計中,作為網路設計 TCP/IPTCP/IP 的橋樑的橋樑

SocketSocket 是一個簡單的應用程式介面是一個簡單的應用程式介面 (Application Programming (Application Programming Interface, API)Interface, API)

SocketSocket 使發展網路程式變得比較簡單。目前,使發展網路程式變得比較簡單。目前, SocketSocket 已成為最通用的已成為最通用的網路設計介面了。 網路設計介面了。

Berkeley Socket InterfaceBerkeley Socket Interface 是一組是一組 interface functioninterface function ,介於網路應用,介於網路應用程式和作業系統及網路硬體之間,用以提供標準的函數,應用程式可透過程式和作業系統及網路硬體之間,用以提供標準的函數,應用程式可透過呼叫呼叫 Socket interfaceSocket interface 以發展以發展 TCP/IPTCP/IP 的網路應用程式。 的網路應用程式。

BSD ( Berkeley Software Distribution ) Socket BSD ( Berkeley Software Distribution ) Socket

WinSock WinSock

LINK

Page 7: 網路程式設計 - Socket 程式設計

77

應用程式與應用程式與 SocketSocket 關係關係

應用程式 1應用程式 1 應用程式 2應用程式 2 應用程式 3應用程式 3 應用程式 4應用程式 4

網路程式介面 API (BSD Socket 或 Win Sock)網路程式介面 API (BSD Socket 或 Win Sock)

TCP/IPTCP/IP

作業系統作業系統

網路卡網路卡

Page 8: 網路程式設計 - Socket 程式設計

88

SocketSocket 概念概念 SocketSocket 的概念和檔案代碼觀念相似,一個的概念和檔案代碼觀念相似,一個 SocketSocket

就是一個通訊點,以一個就是一個通訊點,以一個整數整數來表示之。來表示之。

SocketSocket 並不是並不是 TCPTCP 或或 UDPUDP 的的 port numberport number

SocketSocket 只是一個代碼代表網路協定中的只是一個代碼代表網路協定中的一組資料一組資料• TCPTCP 連線中雙方的連線中雙方的 IPIP 位址位址• 目前連線的狀態目前連線的狀態

Page 9: 網路程式設計 - Socket 程式設計

99

Socket DescriptorSocket Descriptor

Socket( 整數 )

Page 10: 網路程式設計 - Socket 程式設計

1010

主機1主機1 主機 2主機 2

TCP 或 UDPTCP 或 UDP

AP1AP1 AP2AP2 AP3AP3 AP3AP3

80 333321 23

Page 11: 網路程式設計 - Socket 程式設計

1111

大綱大綱 TCP/IPTCP/IP 協定複習協定複習

什麼是什麼是 Socket?Socket?

Socket APISocket API 的使用的使用

SocketSocket 相關的資料結構相關的資料結構

主要的主要的 Socket APISocket API

Page 12: 網路程式設計 - Socket 程式設計

1212

Socket(Socket( 連結導向連結導向 ), TCP), TCP

socket()socket()

connect()connect()

write()write()

read()read()

socket()socket()

bind()bind()

read()read()

write()write()

listen()listen()

accept()accept()

建立連線Client Server

Page 13: 網路程式設計 - Socket 程式設計

1313

write()

write()

read()

read()

使用 write() 及 read() 來傳送與接收資料

Page 14: 網路程式設計 - Socket 程式設計

1414

Socket(Socket( 非連結導向非連結導向 ), UDP), UDP

socket()socket()

bind()bind()

sendto()sendto()

recvfrom()recvfrom() sendto()sendto()

Client Server

socket()socket()

bind()bind()

recvfrom()recvfrom()

Page 15: 網路程式設計 - Socket 程式設計

1515

Client/ServerClient/Server 模型模型 ClientClient 端:端:1.1. ClientClient 開啟一個開啟一個 socketsocket 並且使用一個並且使用一個 portport

2.2. ClientClient 使用使用 connectconnect 以建立連結以建立連結 TCPTCP 要經過三向交握要經過三向交握

3.3. ClientClient 使用使用 read/write system callread/write system call 對開啟的對開啟的 socketsocket 做讀做讀寫的動作寫的動作

4.4. 關閉關閉 socketsocket 以結束連結以結束連結

Page 16: 網路程式設計 - Socket 程式設計

1616

open socket 由作業系統如同檔案一般取得一 Socket Descriptor ,讓 Client 端以後可使用這一代號進行網路I/O 讀寫。

bind 是指定 Client 端使用 local ( 也就是本機 ) 的哪一 IP及 Port 進行通訊。若無指定,則連線時由系統幫 Client 程式自動挑選合適的 IP 與 Port 。因此對 Client 端而言是 Optional 。

connect 是起始 TCP 的連線,配合 Server 端的 accept System Call 完成三向交握,因此於 connect 此 System Call 必需傳給予對方 Server 端的 IP 與 Port 的資訊。

read/write 針對已經完成連線的 Socket Descriptor 進行 I/O 動作,在此傳送 HTTP 的 Protocol 並得到 Server 回傳的 HTML 檔案內容等。

close 關閉 TCP 連線,釋放系統資源。

socket()socket()

bind()bind()

connect()connect()

read()write()read()write()

close()close()

Page 17: 網路程式設計 - Socket 程式設計

1717

Client/ServerClient/Server 模型模型 ServerServer 端:端:1.1. ServerServer 開啟一個開啟一個 socketsocket 並佔用一個並佔用一個 portport

2.2. 使使 socketsocket 進入被動模式來等待進入被動模式來等待 clientclient 的連結的連結

3.3. ServerServer 及及 clientclient 利用利用 read/write system callread/write system call 進行對開啟進行對開啟的的 socketsocket 做讀寫的動作做讀寫的動作

4.4. 關閉關閉 socketsocket 以結束連結以結束連結

Page 18: 網路程式設計 - Socket 程式設計

1818

open socket 由作業系統如同檔案一般取得一 Socket Descriptor ,讓 Server 端以後可使用這一代號進行接受外來 TCP 連線。

bind 是指定 Server 端使用 local 的哪一 IP 及 Port 進行通訊。對 Server 端而言是必需的。

listen 表示讓此開啟的 Socket 進入被動模式,配合 accept System Call 可接受外來之連線。

Server 端的 accept System Call 接受 Client 之 connect System Call 完成三向交握,並產生一新的 Descriptor ,此 Descriptor 即為與 Client 進行 I/O 的代號。

read/write 針對已經 accept 產生之 Descriptor 進行 I/O 動作,在此傳送 HTTP 的 Protocol 並得到 Server 回傳的 HTML 檔案內容等。

close 關閉 TCP 連線,釋放系統資源。

socket()socket()

bind()bind()

listen()listen()

read()write()read()write()

close()close()

accept()accept()

Page 19: 網路程式設計 - Socket 程式設計

1919

範例範例 (Client(Client 端端 ) 1/2) 1/2// 建立 socket ,若成功傳回 socket descriptor ,若傳回 -1 表 error if((sockfd=socket(AF_INET, SOCK_STREAM, 0)) == -1) { printf("Socket Error:%s\a\n", strerror(errno)); printf("Socket Error:%s\a\n", strerror(errno)); exit(1); } // 填入 family, address, port ,另外,其他地方要填入 0( 使用 bzero() function) bzero((char*) &server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(portnumber); server_addr.sin_addr = *((struct in_addr *) host->h_addr); // 和 Server 建立連線 if(connect(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1) { printf("Connect Error:%s\a\n", strerror(errno)); exit(1); }

140.134.26.50

Most Significant byte first (Network Byte Order)

Least Significant byte first ( 大部分 Host Byte Order)

140 134 26 50

50 26 134 140

Page 20: 網路程式設計 - Socket 程式設計

2020

範例範例 (Client(Client 端端 ) 2/2) 2/2// 送資料 (hello 字串 ) 給 Server if(write(sockfd, hello, strlen(hello)) == -1) { printf("Write Error:%s\n", strerror(errno)); exit(1); } // 從 Server 收資料 if((nbytes=read(sockfd, buffer, 1024)) == -1) { printf("Read Error:%s\n", strerror(errno)); exit(1); } buffer[nbytes] = '\0'; printf("I am Client. I have received from Server:%s\n", buffer); close(sockfd); exit(0);

Page 21: 網路程式設計 - Socket 程式設計

2121

範例範例 (Server(Server 端端 ) 1/3) 1/3// 建立 socket ,若成功傳回 socket descriptor ,若傳回 -1 表 error if((sockfd=socket(AF_INET,SOCK_STREAM,0)) == -1) { printf("Socket error:%s\n\a", strerror(errno)); exit(1); } // 填入 family, address, port ,另外,其他地方要填入 0( 使用 bzero() function) bzero((char*)&server_addr,sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(portnumber); //port number, 以 htons(16 bytes) 轉成 network byte order server_addr.sin_addr.s_addr = htonl(INADDR_ANY); //htonl is for 32-bytes, binary presentation // 連接通訊埠 if(bind(sockfd, (struct sockaddr *)(&server_addr), sizeof(struct sockaddr)) == -1) { printf("Bind error:%s\n\a", strerror(errno)); exit(1); }

Page 22: 網路程式設計 - Socket 程式設計

2222

範例範例 (Server(Server 端端 ) 2/3) 2/3// 進入被動狀態,等待連線 if(listen(sockfd,5) == -1) { printf("Listen error:%s\n\a", strerror(errno)); exit(1); }

while(1) { sin_size = sizeof(struct sockaddr_in); // 接受連線,並產生一個新的 socket(new_fd) ,傳回 -1 表失敗 // 其中 client 的 address 將放在 client_addr 中 if((new_fd=accept(sockfd, (struct sockaddr *)(&client_addr), &sin_size)) == -1) { fprintf(stderr, "Accept error:%s\n\a", strerror(errno)); exit(1); }

printf("Server get connection from %s\n", inet_ntoa(client_addr.sin_addr));

Page 23: 網路程式設計 - Socket 程式設計

2323

範例範例 (Server(Server 端端 ) 3/3) 3/3// 將資料讀進放入 buffer 陣列中 if((nbytes=read(new_fd, buffer, 1024)) == -1) { printf("Read Error:%s\n", strerror(errno)); exit(1); } buffer[nbytes] = '\0'; printf("I have received:%s\n", buffer); // 把 hello 字串的資料傳回 client if(write(new_fd, hello, strlen(hello)) == -1) { printf("Write Error:%s\n", strerror(errno)); exit(1); } close(new_fd); } close(sockfd); exit(0);

Page 24: 網路程式設計 - Socket 程式設計

2424

Page 25: 網路程式設計 - Socket 程式設計

2525

大綱大綱 TCP/IPTCP/IP 協定複習協定複習

什麼是什麼是 Socket?Socket?

Socket APISocket API 的使用的使用

SocketSocket 相關的資料結構相關的資料結構

主要的主要的 Socket APISocket API

Page 26: 網路程式設計 - Socket 程式設計

2626

SocketSocket 相關資料結構相關資料結構 struct    sockaddr struct    sockaddr struct    sockaddr_instruct    sockaddr_in struct    in_addrstruct    in_addr struct    hostentstruct    hostent struct    serventstruct    servent struct    protoentstruct    protoent

Page 27: 網路程式設計 - Socket 程式設計

2727

sockaddr sockaddr

<sys/socket.h>

// 一般化的位址struct sockaddr {   

u_short         sa_family;   /* type of address, AF_INET, AF_INET (Internet protocol address family) */char              sa_data[14];              /* value of address, specifies the address value */

};

Page 28: 網路程式設計 - Socket 程式設計

2828

sockaddr_in sockaddr_in

<netinet/in.h>

//IPv4 Socket Addressstruct sockaddr_in {                           

u_short                  sin_family;           //specifies protocol to use, PF_INET for either of TCP or UDPu_port                   sin_port;             //16 bits, network byte orderstruct in_addr      sin_addr;             //32 bits, network byte order

    char                      sin_zero[8];         //unused

};

Page 29: 網路程式設計 - Socket 程式設計

2929

一般位址一般位址 IPv4 Socket AddressIPv4 Socket Address

Page 30: 網路程式設計 - Socket 程式設計

3030

in_addr

//Internet address structure struct in_addr {                             

long           s_addr;                 //32-bit( 整數 ) IPv4 address, network byte ordered

};

Page 31: 網路程式設計 - Socket 程式設計

3131

hostentstruct hostent {

char               *h_name;    char               **h_aliases;    int                  h_addrtype;    int                  h_length;    char               **h_addr_list;                       

//hptr->h_addr = gethostbyname(“140.134.26.21”);};

#define      h_addr              h_addr_list[0]

h_addr_list[0]

h_addr_list[1]

h_addr_list

……

Page 32: 網路程式設計 - Socket 程式設計

3232

servent servent

struct servent {    char         *s_name;

char         **s_aliases;    int            s_port;    char         *s_proto;};

Page 33: 網路程式設計 - Socket 程式設計

3333

protoent protoent

struct protoent {    char       *p_name;    char       **p_aliases;    int          p_proto;};

Page 34: 網路程式設計 - Socket 程式設計

3434

大綱大綱 TCP/IPTCP/IP 協定複習協定複習

什麼是什麼是 Socket?Socket?

Socket APISocket API 的使用的使用

SocketSocket 相關的資料結構相關的資料結構

主要的主要的 Socket APISocket API

Page 35: 網路程式設計 - Socket 程式設計

3535

主要的主要的 Socket APISocket API socketsocket

• 建立建立 socketsocket bindbind

• 設定設定 socketsocket 所使用的所使用的 local IPlocal IP 及通訊埠及通訊埠 listenlisten

• 設定設定 socketsocket 等待等待 clientclient 的連結請求的連結請求 acceptaccept

• 接受來自接受來自 clientclient 的連結請求,並建立的連結請求,並建立 socketsocket 連結連結 recv/readrecv/read

• (TCP)(TCP) 接收來自接收來自 clientclient 所傳的資料所傳的資料 recvfromrecvfrom

• (UDP)(UDP) 接收來自接收來自 clientclient 所傳的資料所傳的資料 send/writesend/write

• (TCP)(TCP) 傳送資料到傳送資料到 clientclient sendtosendto

• (UDP)(UDP) 傳送資料到傳送資料到 clientclient

Server

Page 36: 網路程式設計 - Socket 程式設計

3636

主要的主要的 Socket APISocket API socketsocket

• 建立建立 socketsocket connectconnect

• 建立與建立與 serverserver 端端 socketsocket 連線 連線 recv/readrecv/read

• (TCP)(TCP) 接收來自接收來自 serverserver 所傳的資料 所傳的資料 recvfromrecvfrom

• (UDP)(UDP) 接收來自接收來自 serverserver 所傳的資料 所傳的資料 send/writesend/write

• (TCP)(TCP) 傳送資料到傳送資料到 server server sendtosendto

• (UDP)(UDP) 傳送資料到傳送資料到 server server

Client

Page 37: 網路程式設計 - Socket 程式設計

3737

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

參數:family: Selects the protocol family to be used; defined in <sys/socket.h>; use PF_INET for TCP or UDP. 其他還有 PF_UNIXAF_INET          IPv4AF_INET6        IPv6AF_LOCAL      Unix domain protocols ~ IPCAF_ROUTE      Routing sockets ~ appls and kernelAF_KEY           Key socketAF_UNIXAF_IMPLINKtype: Semantics of desired communication protocol; defined in <sys/socket.h>; SOCK_STREAM for TCP; SOCK_DGRAM for UDP; others are possible.SOCK_STREAM     stream socketSOCK_DGRAM      datagram socketSOCK_RAW           raw socketSOCK_PACKET     datalink (Linux)protocol: Normally only one per type; defined in /etc/protocols; 6 for TCP, 17 for UDP; Can use 0 (zero) and the socket call will figure out the right protocol to use for the specified type field. 傳回值:Return: return a integer identifier called a handle. (nonnegative descriptor if OK, negative number on error) 範例:Example:  To create a TCP socket:    int sock;    sock = socket(PF_INET, SOCK_STREAM, 0);

Page 38: 網路程式設計 - Socket 程式設計

3838

int connect(int s, struct sockaddr *name, int namelen); int connect(int s, struct sockaddr *name, int namelen);

參數:s: file descriptor of socket; returned by call to socket.name: address of the socket data structure; must fill-in this structure before calling connect.namelen: length of name data structure; sizeof(name).

範例:Example:if(connect(fd, (struct sockaddr*) &srv, sizeof(srv)) < 0) {    perror(”connect"); exit(1);}

Page 39: 網路程式設計 - Socket 程式設計

3939

int bind(int socket, const struct sockaddr *address, int addrlen); int bind(int socket, const struct sockaddr *address, int addrlen);

功能:Server 端的 TCP 或 UDP 會使用到連結 socket 到特定的 address (IP address & TCP/UDP port)

參數:socket: Descriptor identifying an unbound socket. (returned by the socket function.)address: A pointer to a protocol-specific addressaddrlen: Length of the value in the name parameter, in bytes.

範例:Example:if(bind(fd, (struct sockaddr*) &srv, sizeof(srv)) < 0) {    perror("bind");     exit(1);}

Page 40: 網路程式設計 - Socket 程式設計

4040

int listen(int s, int backlog); int listen(int s, int backlog);

if(listen(fd, 5) < 0) {    perror(“listen”);    exit(1);}

Page 41: 網路程式設計 - Socket 程式設計

4141

int accept(int s, struct sockaddr *addr, socklen_t int accept(int s, struct sockaddr *addr, socklen_t *addrlen);*addrlen);

參數:s: the socket the Server is listening to.addr will be the address (IP + port) of the client that sent the connection request.

傳回值:Return: (new) socket for communicating with this client. 範例:Example:newfd = accept(fd, (struct sockaddr*) &cli, &cli_len);if(newfd < 0) {    perror("accept"); exit(1);}

Page 42: 網路程式設計 - Socket 程式設計

4242

int send (int socket, char *message, int msg_len, intflags) (TCP) int send (int socket, char *message, int msg_len, intflags) (TCP)

int write(int socket, void *msg, int len); (TCP) int write(int socket, void *msg, int len); (TCP)

int recv (int socket, char *buffer, int buf_len, int flags) (TCP) int recv (int socket, char *buffer, int buf_len, int flags) (TCP)

Page 43: 網路程式設計 - Socket 程式設計

4343

int read(int socket, void *msg, int len); (TCP) int read(int socket, void *msg, int len); (TCP)

範例:Example:int fd;                    /* socket descriptor */char buf[512];       /* used by read() */int nbytes;             /* used by read() */if((nbytes = read(newfd, buf, sizeof(buf))) < 0) {    perror(“read”);     exit(1);}

Page 44: 網路程式設計 - Socket 程式設計

4444

int sendto (int socket, void *msg, int len, int flags, struct int sendto (int socket, void *msg, int len, int flags, struct sockaddr * to, int tolen ); (UDP) sockaddr * to, int tolen ); (UDP)

參數:socket: Descriptor identifying a bound socket.msg: Buffer containing the data to be transmitted.len: Length of the data in buf, in bytes. flags: Indicator specifying the way in which the call is made. (usually set to 0)to: Optional pointer to a sockaddr structure that contains the address of the target socket. tolen: Size of the address in to, in bytes.

範例:Example:int fd;                                  /* socket descriptor */struct sockaddr_in srv;         /* used by sendto() */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 , (struct sockaddr*) &srv, sizeof(srv));if(nbytes < 0) {    perror(“sendto”); exit(1);}

Page 45: 網路程式設計 - Socket 程式設計

4545

int recvfrom(int socket, void *msg, int len, int flags, struct int recvfrom(int socket, void *msg, int len, int flags, struct sockaddr *from, int *fromlen); (UDP) sockaddr *from, int *fromlen); (UDP)

範例:Example:int fd;                                    /* socket descriptor */struct sockaddr_in srv;          /* used by bind() */struct sockaddr_in cli;           /* used by recvfrom() */char buf[512];                       /* used by recvfrom() */int cli_len = sizeof(cli);         /* used by recvfrom() */int nbytes;                             /* used by recvfrom() */nbytes = recvfrom(fd, buf, sizeof(buf), 0 /* flags */,

(struct sockaddr*) &cli, &cli_len);if(nbytes < 0) {    perror(“recvfrom”); }

Page 46: 網路程式設計 - Socket 程式設計

4646

unsigned long int htonl(unsigned long int hostlong);unsigned long int htonl(unsigned long int hostlong);• Host-to-network byte order for a long word (4 bytes) Host-to-network byte order for a long word (4 bytes)

unsigned short int htons(unsigned short int hostshort);unsigned short int htons(unsigned short int hostshort);• Host-to-network byte order for a short word (2 bytes) Host-to-network byte order for a short word (2 bytes)

unsigned long int ntohl(unsigned long int netlong);unsigned long int ntohl(unsigned long int netlong);• Network-to-host byte order for a long word Network-to-host byte order for a long word

unsigned short int ntohs(unsigned short int netshort);unsigned short int ntohs(unsigned short int netshort);• Network-to-host byte order for a short word Network-to-host byte order for a short word

Page 47: 網路程式設計 - Socket 程式設計

4747

struct hostent *gethostbyname (const char *hostname); struct hostent *gethostbyname (const char *hostname);

定義在 <netdb.h> 中struct hostent {    char           *h_name;                /* official (canonical) name of host */    char           **h_aliases;            /* ptr to array of ptrs to alias names */    int              h_addrtype;               /* host addr type: AF_INET or AF_INET6 */    int              h_length;                    /* length of address: 4 or 16 */    char           **h_addr_list;         /* ptr to array of ptrs with IPv4/IPv6 addrs */};#define h_addr h_addr_list[0] /* first address in list */