套接字的连接(服务器与客户端一对一的连接)
(2):套接字類型:一個套接字域可能有多種不同的通信方式,而每種通信方式又有其不同的特性,但是AF_UNIX(是一臺還未聯(lián)網(wǎng)的計算機上的套接字)域的套接字沒有這樣的問題,它們提供了一個可靠的雙向通信路徑。在網(wǎng)絡(luò)域中就需要注意底層網(wǎng)絡(luò)的特性,以及不同的通信機制是如何受到它們的影響的。因特網(wǎng)協(xié)議提供了兩種通信機制:流、數(shù)據(jù)報。? 1)流套接字:它的行為是可預(yù)見的,它提供的是一個有序、可靠、雙向字節(jié)流的鏈接。發(fā)送的數(shù)據(jù)可以確保不丟失、復(fù)制或亂序到達(dá),并且再這一過程中發(fā)生的錯誤也不會顯示出來。大的消息將被分片、傳輸、再重組。流套接字由類型SOCK_STREAM指定,它們是在AF_INET域中通過TCP/IP鏈接實現(xiàn)的。TCP/IP代表的是傳輸控制協(xié)議/網(wǎng)際協(xié)議。IP協(xié)議是針對數(shù)據(jù)包的底層協(xié)議,它提供從一臺計算機通過網(wǎng)絡(luò)到達(dá)另一臺計算機的路由。TCP協(xié)議提供排序、流控和重傳,以確保大數(shù)據(jù)的傳輸可以完整地到達(dá)目的地或報告一個適當(dāng)?shù)腻e誤條件。??????????????????????????????????????????????????????????????????????????? ?2)數(shù)據(jù)報套接字:與流套接字相反,由SOCK_DGRAM指定的數(shù)據(jù)包套接字不建立和維持一個鏈接,可以對發(fā)送的數(shù)據(jù)包長度有限制,數(shù)據(jù)報可能會丟失、復(fù)制或亂序到達(dá)。數(shù)據(jù)報套接字是在AF_INET中通過UDP/IP連接實現(xiàn)的,它提供的是一種無序的、不可靠的服務(wù)。從資源角度看,相對來說它們開銷較小,因為不需要維持網(wǎng)絡(luò)連接。因為不需要花費時間來建立連接,所以它們的速度也很快。優(yōu)點:服務(wù)器的崩潰不會給客戶造成不便,也不會要求客戶重啟,因為基于數(shù)據(jù)報的服務(wù)器通常不保留連接信息,所以它們可以再不打擾其客戶的前提下通知并重啟。
代碼部分:服務(wù)器端:
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<string.h> #include<assert.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h>int main() {//創(chuàng)建套接字,并返回一個描述符,該描述符可以訪問套接字//AF_INET是IPV4和ARPA因特網(wǎng)指定的協(xié)議//第二個參數(shù)是通信類型,而此處SOCK_STREAM(流服務(wù)),對AF_INET域套接字來說它默認(rèn)是通過TCP連接來提供這一特性//第三個參數(shù)是指定使用的協(xié)議,但是通信所使用的協(xié)議一般是由套接字的域和套接字類型來決定,通常不需要選擇int sockfd = socket(AF_INET,SOCK_STREAM,0);assert(sockfd != -1);//ipv4專用的struct sockaddr_in saddr, caddr; //該結(jié)構(gòu)體指定了自己的ip地址和端口memset(&saddr,0,sizeof(saddr)); //將socket置空//在AF_INET域種,套接字的地址由結(jié)構(gòu)sockaddr_in來指定,頭文件netinet/in.hsaddr.sin_family = AF_INET;saddr.sin_port = htons(6000); //<1024 root saddr.sin_addr.s_addr = inet_addr("127.0.0.1");//自己的ip地址是多少就寫多少,用ifconfig查,如果沒有192...就用172.0.0.1,//命名套接字作用:通過socket調(diào)用創(chuàng)建的套接字可以被其他進程使用listen(sockfd,5); //創(chuàng)建監(jiān)聽隊列,這種機制允許當(dāng)服務(wù)器程序正忙于處理前一個客戶請求的時候,將后續(xù)的客戶連接放入隊列等待處理,backlog參數(shù)通常是5,舉例:假設(shè)只有一個門迎,門迎接客之后交接給店內(nèi)的服務(wù)員然后再去迎接下一位客人。while(1){int len = sizeof(caddr);int c = accept(sockfd,(struct sockaddr*)&caddr,&len);//accept函數(shù)將創(chuàng)建一個新的套接字來與客戶進行通信,并返回新的套接字的描述符。新套接字的類型和服務(wù)器監(jiān)聽套接字類型是一樣的。// 舉例: accept門迎,c是新的服務(wù)員點餐,一個服務(wù)員只服務(wù)桌客人,每桌服務(wù)員會不一樣,所以c每次從客戶端接收的數(shù)據(jù)也不一樣 c是你和飯店溝通的橋梁那么,c和客戶端溝通的橋梁,每個c不一樣if(c < 0){continue;}printf("accept(c = %d),ip:%s,port:%d\n",c,inet_ntoa(caddr.sin_addr),ntohs(caddr.sin_port));char buff[128] = {0};recv(c,buff,127,0);printf("buff = %s\n",buff);send(c,"ok",2,0);close(c); //一定要關(guān)閉它,結(jié)束套接字的連接} }????客戶端:????????
#include<stdio.h> #include<stdlib.h> #include<unistd.h> #include<assert.h> #include<string.h> #include<sys/socket.h> #include<netinet/in.h> #include<arpa/inet.h>int main() { // int sockfd = socket(AF_INET,SOCK_STREAM,0); //創(chuàng)建套接字,assert(sockfd != -1);struct sockaddr_in saddr;memset(&saddr,0,sizeof(saddr));saddr.sin_family = AF_INET;saddr.sin_port = htons(6000);saddr.sin_addr.s_addr = inet_addr("192.168.1.102");//指定的是服務(wù)器端的,客戶端和服務(wù)器此處的ip必須一樣才能鏈接成功//(struct sockaddr*)&saddr強轉(zhuǎn),因為一般用的是通用的地址結(jié)構(gòu),而本次代碼用的IPV4,所以改成IPV4的專用地址結(jié)構(gòu)int res = connect(sockfd,(struct sockaddr*)&saddr,sizeof(saddr));assert(res != -1); char buff[128] = {0};printf("input:\n");fgets(buff,128,stdin);send(sockfd,buff,strlen(buff),0);//先發(fā)送數(shù)據(jù),然后清空buff,然后再將收到的數(shù)據(jù)存放在buffmemset(buff,0,128);recv(sockfd,buff,127,0);printf("buff = %s\n",buff);close(sockfd); }?
????
?
總結(jié)
以上是生活随笔為你收集整理的套接字的连接(服务器与客户端一对一的连接)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: Android 虚拟分区详解(三) 分区
- 下一篇: android虚拟内置sd卡,安卓虚拟器