Socket學習筆記

2022-10-08 03:51:09 字數 4746 閱讀 3700

插板插座

網路套接字

在通訊過程中,套接字一定是成對存在的

兩份套接字,c乙個 s乙個

乙個檔案描述符指向乙個套接字(該套接字內部由核心借助兩個緩衝區實現)

網路位元組序

大端法

例如udp段格式,位址0-1是16位的源埠號,如果這個埠號是1000 (0x3e8), 則位址0是0x03, 位址1是0xe8, 也就是先發0x03,再發0xe8,這16位在傳送主機的緩衝區中也應該是低位址存0x03, 高位址存0xe8。但是,如果傳送主機是小端位元組序的,這16位被解釋成0xe803, 而不是1000。 因此,傳送主機把1000填到傳送緩衝區之前需要做位元組序的轉換。同樣地,接收主機如果是小端位元組序的,接到16位的源埠號也要做位元組序的轉換。如果主機是大端位元組序的,傳送和接收都不需要做轉換。同理,32位的ip位址也要考慮網路位元組序和主機位元組序的問題。

htonl 是將本地的32位整型數轉換為網路位元組序。 主要是用於ip的轉換。

192.168.1.11 --> string -->atoi -->int -->htonl -->網路位元組序

int inet_pton (int af ,const char *src, void *dst)

af 指代當前協議,ipv4 (af_inet)或者ipv6 (af_inet6)

src 傳入ip位址 (點分十進位制)

dst 傳出 轉換後的 網路位元組序的ip位址

返回值:

成功:1

失敗: -1

const char *inet_ ntop(int af,const void * src, char * dst, socklen_t size);網路位元組序--->本地位元組序(string ip)af: af_inet、af_inet6src:網路位元組序ip位址dst:本地位元組序(string ip) size: dst 的大小。

返回值:成功:dst

失敗 : null

struct  sockaddr_in add;

第乙個引數add.sin_family = af_inet

第二個引數add.sin_port = htons(8080);

第三個引數是結構體add.sin_addr.s_addr

但是一般是用add.sin_addr.s_addr = htonl( inaddr_any) (取出系統中任意有效的ip位址,是二進位制型別,所以用htonl進行轉換)

流程

tcp服務端同socket函式生成乙個套接字,套接字中有檔案描述符,這個檔案描述符相當於控制代碼,乙個入口。然後呼叫bind()函式將埠號和ip繫結,再呼叫listen() listen的作用是設定監聽上限,就是乙個引數設定。再進行呼叫accept()是阻塞監聽客戶端連線。accept的引數中包含著之前用socket()生成的套接字的控制代碼。然後accept函式會返回乙個新的socket()。這個新的socket 和客戶端的套接字進行通訊。

tcp客戶端通過socket()新建了乙個套接字,然後通過connect()進行連線。connect()中要繫結ip和port 。此時服務端和客戶端就連線在了一起,整個系統中存在三個socket(),一對和乙個獨立的,一對的是進行連線通訊的,單獨的那個是進行監聽的。

int socket(int domain, int type, int protocol);
domain是指定當前的ip協議是哪個,例如我們選擇af_inet即ipv4.

type指定當前套接字的資料傳輸協議。期中有流式傳輸stream, 報式協議sock_dgram

protocol : 表示所選協議中的代表協議,一般我們都是傳0.

舉例: type的引數是stream時,protocol的引數是0,就表示當前協議是tcp,如果type是dgram,protocol的引數是0,就表示單前協議是udp

返回值:如果成功就返回新套接字所對應的檔案描述符。

失敗就是 -1 errno。

舉例:fd= socket(af_inet,sock_stream,0) 就是返回乙個ipv4的tcp協議的套接字。

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
給socket 繫結乙個位址結構(ip+port)

sockfd 就是socket函式返回值

addr 就是sockaddr 位址結構,要分別對三個引數進行初始化。

這個結構體和引數中需要的結構體不同,所以初始化完了之後要進行強轉。

例如:

struct sockaddr_in addr ;

​addr.sin_family = af_inet;   //(和前面使用的ip協議相同)

​addr.sin_port = htons(8080);

​addr.sin_addr.s_addr = htonl(inaddr_any);

​addr :(struct sockaddr *) &addr ;

​addrlen :sizeof(addr)  位址結構的大小

返回值:

成功: 0

失敗: -1 errno

int listen(int sockfd, int backlog);
設定同時與伺服器建立連線的上限數(同時進行三次握手的客戶端數量)

sockfd: socket的控制代碼

backlog : 上限數值, 最大值為128

成功:返回0

失敗: 返回-1

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

​#define _gnu_source             /* see feature_test_macros(7) */

#include

​int accept4(int sockfd, struct sockaddr *addr,socklen_t *addrlen, int flags);

阻塞等待客戶端建立連線,成功返回乙個與客戶端成功連線socket檔案描述符。用乙個socket返回乙個新socketsockfd: socket的控制代碼

addr : 和bind 的引數差乙個關鍵字const ,上乙個是傳入引數,這個是傳出引數,即傳出的是成功與伺服器建立連線的那個客戶端的位址結構。

addrlen : 入:addr的大小 出:客戶端addr的實際大小

返回值:

成功:能與客戶端進行資料通訊的socket對應的檔案描述。

失敗: -1 errno

乙個埠肯定只能繫結乙個socket。伺服器端的埠在bind的時候已經繫結到了監聽套接字socetfd所描述的物件上,accept函式新建立的socket物件其實並沒有進行埠的占有,而是複製了socetfd的本地ip和埠號,並且記錄了連線過來的客戶端的ip和埠號。

那麼,當客戶端傳送資料過來的時候,究竟是與哪乙個socket物件通訊呢?

客戶端傳送過來的資料可以分為2種,一種是連線請求,一種是已經建立好連線後的資料傳輸。

由於tcp/ip協議棧是維護著乙個接收和傳送緩衝區的。在接收到來自客戶端的資料報後,伺服器端的tcp/ip協議棧應該會做如下處理:如果收到的是請求連線的資料報,則傳給監聽著連線請求埠的socetfd套接字,進行accept處理;如果是已經建立過連線後的客戶端資料報,則將資料放入接收緩衝區。這樣,當伺服器端需要讀取指定客戶端的資料時,則可以利用socketfd_new 套接字通過recv或者read函式到緩衝區裡面去取指定的資料(因為socketfd_new代表的socket物件記錄了客戶端ip和埠,因此可以鑑別)。

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
與伺服器建立連線。

sockfd : 客戶端socket函式返回值。

addr : 傳入引數, 伺服器的位址結構 。

返回值:

成功 :0

失敗: -1 errno

這邊不使用bind 函式進行繫結的話,就採用了「隱式繫結」。

tcp通訊流程分析:

server:

socket( ) 建立socket

bind ( ) 繫結伺服器位址結構

listen( ) 設定監聽上限

accept() 阻塞監聽客戶端連線

read (fd) 讀socket獲取客戶端資料

小--大寫 toupper ()

write(fd)

close()

client:

socket() 建立socket

connect( ) 與伺服器建立連線

write ( ) 寫資料到socket

read() 讀轉換後的資料。

顯示讀取結果

close

Socket學習筆記

public classsocketextends object 此類實現客戶端套接字 也可以就叫 套接字 套接字是兩台機器之間的通訊端點。套接字的實際工作由socketimpl類的例項執行。應用程式通過更改建立套接字實現的套接字工廠可以配置它自身,以建立適合本地防火牆的套接字。一 建構函式 soc...

socket學習筆記

為了理清思路,做一些小筆記 1 socket流程 int socket 產生了該socket的描述符socket description bind 主動呼叫時,把socket與埠繫結,如果不主動呼叫,在linsten和connect時,會自動隨機分配乙個埠。server端在socket和bind之後...

socket程式設計(學習筆記)

tcp ip協議找到目標位址,埠號標識軟體。public static void main string args throws exception 客戶端 public static void main string args 多執行緒通訊 構造執行緒,執行邏輯 thread thread 1 n...