標籤:const port 發送資料 握手 osi 遊戲 tcp 簡單 turn
瞭解socket,就需要瞭解資料在網路中傳輸。
網路通訊有三要素:ip地址,網路中裝置的表示,例如本機用127.0.0.1,或者用本機名:localhost;連接埠號碼,用來標示進程的邏輯地址,也就是服務,有效連接埠0~65535,一般1024以下連接埠被系統或者本地服務所佔據,開發中盡量不要使用,以避免衝突;通訊協議——UDP,TCP,UDP是使用者資料報文協議,只負責發送資料,並不管是否被接收,不會建立聯結,其會將資料和目的封裝到資料包中。每個包大小為64K以內,資料轉送速度很快,但是並不安全,一般用在遊戲,直播之類的行業中;TCP則需要建立聯結來傳輸資料,不會對資料做大小限制,需要通過三向交握協議來完成串連,安全可靠,缺點便是效率低。
三向交握建立串連:
首先client發送串連請求到伺服器,伺服器同意串連發送ACK報文,並為這次串連分配資源;client接收到ACK報文後,也向伺服器發送ack報文,並為串連分配資源,這樣TCP串連就建立成功。斷開時採用四次揮手協議:
client發送中斷連線請求,FIN報文,伺服器接收到FIN報文了,知道client已經準備好結束串連,不再傳輸資料,但是如果伺服器端沒有準備好,不用著急關閉scoket,仍然可以發送資料前往client,此時需要發送ACK報文,告訴client請等待結束,讓client進去FIN_WAIT狀態。當伺服器確定完成資料發送並可以關閉,發送FIN報文進入client,client接收到FIN報文後,並不會立刻中斷連線,為了避免錯誤關閉狀態,例如伺服器沒打算關閉串連,會向伺服器發送ACK報文,並會進入TIME_WAIT狀態,等待2MSL後未接收到伺服器回應變正式中斷連線,而伺服器在接收到ACK報文後也會中斷連線。
UDP會涉及到資料打包發送,這其中會需要瞭解osi七層模型:
進行資料轉送,首先應用程式層形成源,然後在傳輸層通過TCP/UDP協議封裝,在網路層,確定ip和連接埠號碼(形成socket),建立資料轉送io,在資料連結層打包資料,每一包資料即為一幀,最後通過物理層轉為電訊號,電訊號的傳輸標示採用高低電平,其實就是01資料,即位元據傳輸,所以網路中資料轉送形式都是二進位。
瞭解這麼多後,再來看socket概念。網路通訊就是socket間的通訊,需要兩端都是socket,然後這兩端建立IO傳輸。可以這樣理解,socket是一種網路機制類,執行個體化的具體資訊就是ip+連接埠。當我們使用qq聊天,a手機IP+qq連接埠發送資訊,需要找到b手機IP+qq連接埠才能接收資料;
socket本身是用c語言書寫,方便跨平台使用,使用起來也非常簡單,基本可以歸位五步。一步,建立socket,第二步,建立connect,第三步,write資料,第四步read資料,第五步colse;
首先,開啟終端,輸入命令:nc -lk 1025(監聽連接埠號碼1025)
匯入標頭檔:
#import <sys/socket.h>#import <netinet/in.h>#import <arpa/inet.h>
按操作建立socket串連:
1.建立socket
/** 參數 socket三個參數傳入相應值 domain: 協議域,AF_INET -> IPV4 AF_INET6 -> IPV6 type: Socket 類型,SOCK_STREAM資料流/SOCK_DGRAM資料報文 protocol: IPPROTO_TCP,如果傳入0 那麼會自動根據第二個參數選擇合適的協議 傳回值 socket */ int clientSocket = socket(AF_INET, SOCK_STREAM, 0);
2.串連伺服器
/** 參數 1> 用戶端socket 2> 指向資料結構sockaddr的指標,其中包括目的連接埠和IP地址 3> 結構體資料長度 傳回值 0 成功/其他 錯誤代號 */ struct sockaddr_in severAddr; severAddr.sin_family = AF_INET; //連接埠 severAddr.sin_port = htons(1025); //地址 severAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); int connResult = connect(clientSocket, (const struct sockaddr *)&severAddr, sizeof(severAddr)); if (connResult == 0) { NSLog(@"串連成功!!"); }else{ NSLog(@"失敗了 %d",connResult); return; }
3.write資料,寫入hello world 可以在簡單連接埠看到相應展示
/** 參數 1> 用戶端socket 2> 發送內容地址 3> 發送內容長度 4> 發送方式標誌,一般為0 傳回值 如果成功,則返回傳送的位元組數,失敗則返回SOCKET_ERROR */ NSString * sendMsg =@"hello world"; ssize_t sendLen = send(clientSocket, sendMsg.UTF8String, strlen(sendMsg.UTF8String), 0);
4.read資料,在連接埠下寫入me too可以看到xcode列印結果展示
/** 參數 1> 用戶端socket 2> 接收內容緩衝區地址 3> 接收內容緩衝區長度 4> 接收方式,0表示阻塞,必須等待伺服器返回資料 傳回值 如果成功,則返回讀入的位元組數,失敗則返回SOCKET_ERROR */ uint8_t buffer[1024];//要把空間準備出來! ssize_t recvLen = recv(clientSocket, buffer, sizeof(buffer), 0);
5.最後便是便是關閉socket
close(clientSocket);
iOS學習——Socket