創(chuàng)新互聯(lián)www.cdcxhl.cn八線動態(tài)BGP香港云服務器提供商,新人活動買多久送多久,劃算不套路!
創(chuàng)新互聯(lián)公司堅持“要么做到,要么別承諾”的工作理念,服務領(lǐng)域包括:做網(wǎng)站、成都網(wǎng)站建設(shè)、企業(yè)官網(wǎng)、英文網(wǎng)站、手機端網(wǎng)站、網(wǎng)站推廣等服務,滿足客戶于互聯(lián)網(wǎng)時代的赤壁網(wǎng)站設(shè)計、移動媒體設(shè)計的需求,幫助企業(yè)找到有效的互聯(lián)網(wǎng)解決方案。努力成為您成熟可靠的網(wǎng)絡建設(shè)合作伙伴!代碼下載
服務端代碼下載地址
客戶端代碼下載地址
相關(guān)概念
socket是一個針對TCP和UDP編程的接口,你可以借助它建立TCP連接等。socket是對TCP/IP協(xié)議的封裝,Socket本身并不是協(xié)議,而是一個調(diào)用接口(API),通過Socket,我們才能使用TCP/IP協(xié)議。Socket的出現(xiàn)只是使得程序員更方便地使用TCP/IP協(xié)議棧而已,是對TCP/IP協(xié)議的抽象,從而形成了我們知道的一些最基本的函數(shù)接口。
socket連接:socket連接就是所謂的長連接,理論上客戶端和服務器端一旦建立起連接將不會主動斷掉;但是由于各種環(huán)境因素可能會是連接斷開,比如說:服務器端或客戶端主機down了,網(wǎng)絡故障,或者兩者之間長時間沒有數(shù)據(jù)傳輸,網(wǎng)絡防火墻可能會斷開該連接以釋放網(wǎng)絡資源。所以當一個socket連接中沒有數(shù)據(jù)的傳輸,那么為了維持連接需要發(fā)送心跳消息~~具體心跳消息格式是開發(fā)者自己定義的。
TCP連接的三次握手:
第一次握手:客戶端發(fā)送syn包(syn=j)到服務器,并進入SYN_SEND狀態(tài),等待服務器確認;
第二次握手:服務器收到syn包,必須確認客戶的SYN(ack=j+1),同時自己也發(fā)送一個SYN包(syn=k),即SYN+ACK包,此時服務器進入SYN_RECV狀態(tài);
第三次握手:客戶端收到服務器的SYN+ACK包,向服務器發(fā)送確認包ACK(ack=k+1),此包發(fā)送完畢,客戶端和服務器進入ESTABLISHED狀態(tài),完成三次握手。
握手過程中傳送的包里不包含數(shù)據(jù),三次握手完畢后,客戶端與服務器才正式開始傳送數(shù)據(jù)。理想狀態(tài)下,TCP連接一旦建立,在通信雙方中的任何一方主動關(guān)閉連接之前,TCP 連接都將被一直保持下去。斷開連接時服務器和客戶端均可以主動發(fā)起斷開TCP連接的請求,斷開過程需要經(jīng)過“四次握手”。
socket建立網(wǎng)絡連接的步驟
建立Socket連接至少需要一對套接字,其中一個運行于客戶端,稱為ClientSocket ,另一個運行于服務器端,稱為ServerSocket 。
套接字之間的連接過程分為三個步驟:服務器監(jiān)聽,客戶端請求,連接確認。
1。服務器監(jiān)聽:服務器端套接字并不定位具體的客戶端套接字,而是處于等待連接的狀態(tài),實時監(jiān)控網(wǎng)絡狀態(tài),等待客戶端的連接請求。
2??蛻舳苏埱螅褐缚蛻舳说奶捉幼痔岢鲞B接請求,要連接的目標是服務器端的套接字。為此,客戶端的套接字必須首先描述它要連接的服務器的套接字,指出服務器端套接字的地址和端口號,然后就向服務器端套接字提出連接請求。
3。連接確認:當服務器端套接字監(jiān)聽到或者說接收到客戶端套接字的連接請求時,就響應客戶端套接字的請求,建立一個新的線程,把服務器端套接字的描述發(fā)給客戶端,一旦客戶端確認了此描述,雙方就正式建立連接。而服務器端套接字繼續(xù)處于監(jiān)聽狀態(tài),繼續(xù)接收其他客戶端套接字的連接請求。
BSD socket
BSD socket:完全由c語言實現(xiàn),并且可以在Objective-C代碼中使用。
優(yōu)點:不同平臺中易于移植
缺點:
無法訪問操作系統(tǒng)內(nèi)建的網(wǎng)絡特性(比如系統(tǒng)范圍的VPN)。
更糟糕的是初始化socket連接并不會自動打開設(shè)備的Wi-Fi或是蜂窩網(wǎng)絡,無線網(wǎng)絡會智能的關(guān)閉以節(jié)省電池電量,任何通信連接都會失敗,除非其他網(wǎng)絡進程激活了無線網(wǎng)。
CFNetwork對BSD Socket的分裝可以激活設(shè)備的無線網(wǎng),所以幾乎所有場景都建議使用CFNetwork而不是BSD Socket.
最常用的API:
1.int socket(int, int, int):創(chuàng)建并初始化新的socket,如果成功放回一個文件描述符,如果失敗返回0。
2.int bind(int, const struct sockaddr *, socklen_t):為指定的地址與端口號分配socket。
3.int listen(int, int) __DARWIN_ALIAS(listen):用于服務端監(jiān)聽客戶端
4.int accept(int, struct sockaddr * __restrict, socklen_t * __restrict):接受連接請求,將客戶端地址存儲到clientAddress中。
5.int connect(int, const struct sockaddr *, socklen_t):連接到指定的服務器。
6.ssize_t send(int, const void *, size_t, int):在socket上最多發(fā)送XX數(shù)據(jù)。
7.ssize_t recv(int, void *, size_t, int):在socket上最多讀取XX數(shù)據(jù)。
……
服務端邏輯:如果接收到客戶端發(fā)送過來”1”,那么回復”你猜!”;客戶端發(fā)送過來”2”,那么回復”謝謝!”;客戶端發(fā)送過來”3”,那么回復”對不起!”;客戶端發(fā)送過來”4”,那么回復”好的!”;客戶端發(fā)送過來其他的內(nèi)容,那么一半概率原樣回復,一半概率回復”不知道你在說什么!”。
創(chuàng)建服務端:
1.創(chuàng)建socket
struct sockaddr_in server_addr; server_addr.sin_len = sizeof(struct sockaddr_in); server_addr.sin_family = AF_INET;//AF_INET互聯(lián)網(wǎng)地址簇 server_addr.sin_port = htons(port); server_addr.sin_addr.s_addr = inet_addr(address); bzero(&server_addr.sin_zero, 8); //創(chuàng)建socket int server_socket = socket(AF_INET, SOCK_STREAM, 0);//SOCK_STREAM 有鏈接 if (server_socket == -1) { perror("socket error!"); return 1; }