天天看點

TCP通訊程式設計

1、程式設計模型函數化

TCP通訊程式設計

函數學習

1)建立套接字

函數名:socket

函數原型:Int socket(int domain,int type,int protocol);

函數功能:建立套接字

所屬頭檔案:<sys/types.h>、<sys/socket.h>

傳回值:成功:傳回對應于新套接字的檔案描述符或者套接字的id,失敗:傳回錯誤編碼

參數說明:domain:有一系列可取值;type:建立的套接字協定的類型;protocal:協定

解釋:

int domain,表示套接字要使用的協定簇,協定簇在檔案linux/socket.h有詳細定義,常用的協定簇:

AF_UNIX(本機通信);

AF_INET(TCP/IP -IPv4);

AF_INET6(TCP/IP - IPv6);

其中type參數指的是套接字類型;常用的類型有:

SOCK_STREAM(TCP流);

SOCK_DGRAM(UDP資料報);

SOCK_RAW(原始套接字);

最後一個protocol一般設定為0,也就是當确定套接字使用的協定簇和類型時,這個參數的值就為0,但是有時候建立原始套接字時,并不知道要使用的協定簇和類型,也就是domain參數未知情況下,這時protocol這個參數就起作用了,它可以确定協定的種類。

socket是一個函數,那麼它也有傳回值,當套接字建立成功時,傳回套接字,失敗傳回“-1”,錯誤代碼則寫入“errno”中。

2)綁定套接字

解釋:Socket套接字位址:是一個資料結構,基于TCP傳輸協定為例,其資料結構裡面包含了:

#include<netinet/in.h>

struct sockaddr_in
{
 unsigned short  sin_family;//位址類型,對于基于TCP/IP傳輸協定的通信,該值隻能是AF_INET;
 unsigned shot int sin_port;//表示端口号,範圍在0~65535之間;
 struct in_addr   sin_addr;//32位的IP位址;
 unsigned char  sin_zero[8];//表示填充位元組,一般該值為0;
};      

例子:

struct sockaddr_in Lewis;
  Lewis.sin_family      = AF_INET;
  Lewis.sin_port        = htons(80);
  Lewis.sin_addr.s_addr = inet_addr("202.96.134.133");
  memset(Lewis.sin_zero,0,sizeof(Lewis.sin_zero));      

對于

memset(&servaddr, 0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(6666);      

對于選項INADDR_ANY,就是指的是0.0.0.0的位址,表示所有位址,任意位址,用于一台電腦上有多個網卡的情況,友善管理,管理一個套接字就行,不管資料從哪個網卡過來,隻要是綁定的端口号過來的資料,都可以接收;而用戶端不能使用INADDR_ANY選項;htons   #include <arpa/inet.h> 

    uint16_t htons(uint16_t hostshort); 

    功能: 将一個無符号短整型數值轉換為網絡位元組序,即大端模式(big-endian)

htons 是把你機器上的整數轉換成“網絡位元組序”, 網絡位元組序是 big-endian,也就是整數的高位位元組存放在記憶體的低位址處。而我們常用的 x86 CPU (intel, AMD) 電腦是 little-endian,也就是整數的低位位元組放在記憶體的低位元組處。

舉個例子:假定你的port是  0x1234,  在網絡位元組序裡 這個port放到記憶體中就應該顯示成  addr addr+1  0x12 0x34  而在x86電腦上,0x1234放到記憶體中實際是:  addr addr+1  0x34 0x12 htons 的用處就是把實際記憶體中的整數存放方式調整成“網絡位元組序”的方式。

htonl()  #include <arpa/inet.h>

功能:将主機的無符号長整形數轉換成網絡位元組順序。 

  uint32_t htonl(uint32_t hostlong);

inet_addr() 将一個字元串格式的ip位址轉換成一個uint32_t數字格式,但是需要注意的是, 這個函數的傳回值在大小端機器上是不同的;

例如輸入一個"192.168.0.1"的字元串, 在記憶體中的排列(位元組從低到高) 0xC0, 0xA8 ,0x00 ,0x4A。 那麼在小端序機器上,傳回的數字就是0x4a00a8c0 , 而在大端序機器上則是0xc0a8004a

函數名:bind

函數原型:Int Bind(int sockfd,const struct sockaddr *addr,socklen_t addrlen);

函數功能:綁定套接字:将ip位址與套接字相綁定

所屬頭檔案:<sys/types.h>、<sys/socket.h>

傳回值:成功:傳回對應于新套接字的檔案描述符或者套接字的id;失敗:傳回錯誤編碼

參數說明:sockfd:要綁定套接字的fd;addr:将套接字與那個位址進行綁定;addrlen:位址長度

TCP通訊程式設計
TCP通訊程式設計

網絡位元組序:

TCP通訊程式設計
TCP通訊程式設計

3)監聽

listen
int listen(int sockfd,int backlog)      

作用:1、用來指明伺服器已經做好了準備,可以用來接收客戶機的請求了。2、用來設定伺服器可以接受多少個客戶機的連接配接請求

參數:sockfd與之關聯的套接字的fd。Backlog:客戶機的數目,即允許多少個客戶機來進行連接配接。

成功:傳回0,失敗:傳回-1

4)等待連接配接

Accept
int accept(int sockfd,struct sockaddr *restrict addr,socklen_t *restrict len);      

作用:等待客戶機來進行連接配接,如果無客戶機來連接配接,則導緻伺服器在這裡阻塞。

參數:sockfd:建立的套接字的fd。Addr:如果有客戶機來進行連接配接,那麼通過本位址來傳回客戶機的位址。Len:接收到客戶機的位址的長度

成功:傳回新的套接字的描述符。後面在發送和接收資料時用這個新的fd來進行操作。

5)發送資料

函數名:Send

ssize_t send(int sockfd,const void *buf,size_t nbytes,int flags);

作用:發送資料

參數:sockfd:新的套接字的fd,buf:要發送資料的位址,nbytes:要發送資料的長度,flags:标志

 6)接收資料

Recv
ssize_t recv(int sockfd,void *buf,size_t nbytes,int flags)      

參數:sockfd:新的套接字的fd,buf:要存資料的位址,nbytes:希望接收多大量的資料,flags:标志

7)關閉連接配接

Close

8)連接配接伺服器

Connect
int connect (int sockfd,const struct sockaddr *addr,socklen_t len)      

參數:新建立的套接字的fd,addr:儲存的伺服器的位址,len:伺服器位址的長度

成功:傳回0

失敗:傳回-1

9)

#include <arpe/inet.h>
int inet_pton(int family, const char *strptr, void *addrptr);     //将點分十進制的ip位址轉化為用于網絡傳輸的數值格式      

        傳回值:若成功則為1,若輸入不是有效的表達式則為0,若出錯則為-1

const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);     //将數值格式轉化為點分十進制的ip位址格式      

        傳回值:若成功則為指向結構的指針,若出錯則為NULL

 tcp_server.c

TCP通訊程式設計
TCP通訊程式設計
TCP通訊程式設計

修改:

TCP通訊程式設計
TCP通訊程式設計

tcp_client.c

繼續閱讀