1. 程式人生 > >Linux C 網路程式設計教程

Linux C 網路程式設計教程

1、TCP 套接字通訊工作流程

一.面向連線的套接字Socket通訊工作流程

為了實現伺服器與客戶機的通訊,伺服器和客戶機都必須建立套接字。伺服器與客戶機的工作原理可以用下面的過程來描述。

1.伺服器先用 socket 函式來建立一個套接字,用這個套接字完成通訊的監聽。

2.用 bind 函式來繫結一個埠號和 IP 地址。因為本地計算機可能有多個網址和 IP,每一個 IP 和埠有多個埠。需要指定一個 IP 和埠進行監聽。

3.伺服器呼叫 listen 函式,使伺服器的這個埠和 IP 處於監聽狀態,等待客戶機的連線。

4.客戶機用 socket 函式建立一個套接字,設定遠端 IP 和埠。

5.客戶機呼叫 connect 函式連線遠端計算機指定的埠。

6.伺服器用 accept 函式來接受遠端計算機的連線,建立起與客戶機之間的通訊。

7.建立連線以後,客戶機用 write 函式向 socket 中寫入資料。也可以用 read 函式讀取伺服器傳送來的資料。

8.伺服器用 read 函式讀取客戶機發送來的資料,也可以用 write 函式來發送資料。

9.完成通訊以後,用 close 函式關閉 socket 連線。

 

 

 

2、建立套接字

建立套接字的系統呼叫為socket,它的功能是生成一個套接字的描述符

 #include<sys/types.h>

 #include<sys/socket.h>

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

若成功則返回套接字的描述符,否則返回-1

 

引數family指明協議族,取值如 PF_UNIX(UNIX 協議族)、PF_INET(IPv4協議)、PF_INET6(IPv6協議)、

AF_ROUTE(路由套接字)等;

type指明通訊位元組流型別,其取值如 SOCK_STREAM(TCP方式)、SOCK_DGRAM(UDP方式)、SOCK_RAW(原始套接字)、SOCK_PACKET(支援資料鏈路訪問)。一般來說,引數protocol可設定為0,除非用在原始套接字上。

 

3、繫結埠

  用socket函式建立一個套接字後,需要使用bind函式在這個套接字上繫結一個指定的埠號和IP地址。

 #include<sys/types.h>

 #include<sys/socket.h>

 int bind(int sockfd,const struct sockaddr *my_addr ,socklen_len addrlen);

成功返回0,否則返回-1;

引數中sockfd表示已建立的socket 編號,my_addr 是一個指向sockaddr結構體型別的指標,引數addrlen表示my_addr 結構的長度。

 

4、等待監聽函式

listen函式用於實現伺服器的監聽等待功能

 #include<sys/socket.h>

Int listen(int sockfd,int backlog);

成功返回0,否則返回-1

引數sockfd表示已建立的套接字,backlog表示能同時處理的最大連線請求數目

 

 

5、接受連線函式

  伺服器處於監聽狀態時,如果某時刻獲得客戶機的連線請求,此時並不是立即處理這個請求,而是將這個請求放在等待佇列中,當系統空閒時再處理客戶機的連線請求。接受連線請求的函式是accept函式

#include<sys/types.h>

 #include<sys/socket.h>

 int accept(int sockfd,struct sockaddr *addr,socketlen_t *addrlen);

若成功則返回 新的套接字的描述符,否則返回-1;

  引數sockfd表示處於監聽狀態的socket,addr是一個sockaddr結構體型別的指標,系統會把遠端主機的資訊儲存到這個指標所指向的結構體中,addrlen 表示sockaddr 的記憶體長度。

   當accept函式 接受一個連線時,會返回一個新的socket識別符號,以後的資料傳輸與讀取就是通過這個新的socket編號來處理,原來引數中的socket也可以繼續使用。接受連線以後,遠端主機的地址和埠資訊將會儲存到addr所指的結構體內。如果處理失敗,返回值為-1;

 

 

6、請求連線函式

 connect函式完成請求與伺服器建立TCP通訊連線的功能。

#include<sys/types.h>

 #include<sys/socket.h>

 int connect(int sockfd,const struct sockaddr *serv_addr,int addrlen);

成功返回0,否則返回-1;

 

connect函式會將本地的socket 連線到serv_addr 所指向的伺服器IP 與埠號上去。

 

7、資料傳送函式

 

#include<sys/types.h>

 #include<sys/socket.h>

 int send(int sockfd,const void *msg,int len,unsigned int flads);

成功返回已傳送的位元組數 ,否則返回-1;

引數sockfd表示已經建立的socket,msg是需要傳送資料的指標,len表示需要傳送資料的長度,引數flags一般設定為0.

 

 

8、資料接收函式

函式recv可以接受遠端主機發送來的資料,並把這些資料儲存到一個數組中。

#include<sys/types.h>

 #include<sys/socket.h>

 int recv(int sockfd,void *buf,int len,unsigned int flags);

成功則返回接收到的字元數,否則返回-1

引數sockfd表示已經建立的socket ,buf是一個指標,指向一個數組,接收到的資料會儲存到這個陣列中,len表示陣列的長度,flags一般設定為0.

 

 

9、write和read函式

在網路程式設計中,當socket建立連線後,向這個socket中寫入資料即表示向遠端主機傳送資料,從socket 中讀取資料則相當於接收遠端住居傳送過來的資料。所以,write和read函式也可以用於套接字的程式設計中,他們的作用分別與read和recv函式類似。

#include<unistd.h>

 ssize_t  write (int fd,const void*buf,size_t count);

ssize_t  read (int fd, void*buf,size_t count);

成功則返回已寫入或已讀取的位元組數,若出錯則返回-1;

在引數列表中,fd表示已經建立的socket ,buf是指向一段記憶體的指標,count表示buf指向記憶體的長度。read函式讀取位元組時,會把讀取的內容儲存到buf所指向的記憶體中,然後返回讀取到的位元組的個數。使用write函式傳輸資料時,會把buf指標指向的記憶體中的資料傳送到socket連線的遠端主機,然後返回實際傳送的位元組個數。