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