TCP/IP网络编程复习(上)
生活随笔
收集整理的這篇文章主要介紹了
TCP/IP网络编程复习(上)
小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.
第一章 理解網(wǎng)絡(luò)編程和套接字
#include<sys/socket.h> int socket(int domain, int type , int protocol); //socket返回文件描述符或-1 int bind(int sockfd , struct sockaddr *myaddr, socklen_t addrlen); //bind返回0或-1 int listen(int sockfd,int backlog); //listen返回0或-1 int accept(int sockfd,struct sockaddr *addr,socklen_t *addrlen); //返回文件描述符或-1 ##以上為服務(wù)器端 編譯指令:gcc hello_server.c -o hserver- Linux下socket被認(rèn)為是文件的一種,windows區(qū)分socket和文件
- 0,1,2這三個(gè)文件描述符(方便描述文件)為STDIN STDOUT STDERR
- windows在這方面的函數(shù)與linux差不多,不過(guò)套接字有專屬類型SOCKET
第二章 套接字類型與協(xié)議設(shè)置
- int socket(int domain, int type , int protocol);
第一個(gè)參數(shù)為協(xié)議族有PF_INET PF_INET6等;第二個(gè)參數(shù)為套接字類型:有SOCK_STREAM(傳送帶傳糖果,面向連接,無(wú)數(shù)據(jù)邊界,可靠有序)和SOCK_DGRAM)(摩托車,不可靠,無(wú)序,以數(shù)據(jù)的高速傳輸為目的的套接字);最后一個(gè)參數(shù)默認(rèn)情況是0
第三章 地址族與數(shù)據(jù)序列
- IPV4傳數(shù)據(jù)是先向網(wǎng)絡(luò)號(hào)傳輸數(shù)據(jù)(傳到路由器,交換機(jī)),再由這個(gè)網(wǎng)絡(luò)具體傳給相應(yīng)主機(jī)號(hào)的主機(jī)
- A類地址首字節(jié)范圍:0-127 B:128-191 C:192-223
- NIC(網(wǎng)絡(luò)接口卡)為數(shù)據(jù)傳輸設(shè)備,os會(huì)將傳遞到內(nèi)部的數(shù)據(jù)分配給套接字,這時(shí)需要用到端口號(hào),NIC接收的數(shù)據(jù)內(nèi)有端口號(hào),os參考此端口號(hào)把數(shù)據(jù)傳給對(duì)應(yīng)套接字;端口號(hào)范圍0-65535,但0-1023為知名端口
- 主機(jī)字節(jié)序一般為小端序,網(wǎng)絡(luò)字節(jié)序?yàn)榇蠖诵?/li>
- 數(shù)據(jù)在傳輸之前都需要經(jīng)過(guò)轉(zhuǎn)換嗎:這個(gè)過(guò)程是自動(dòng)的,除了向sockaddr_in結(jié)構(gòu)體變量填充數(shù)據(jù)外,其他情況無(wú)需考慮字節(jié)序問(wèn)題
- p52有兩個(gè)不是特別清楚的點(diǎn),到時(shí)候可以回頭看看
第四章 基于TCP的服務(wù)器端/客戶端(1)
- listen中的sock成為服務(wù)器端套接字,是接收連接或請(qǐng)求的保安
- accept會(huì)內(nèi)部產(chǎn)生一個(gè)用于數(shù)據(jù)I/O的套接字,調(diào)用accept時(shí),若等待隊(duì)列為空,則accept函數(shù)不會(huì)返回,直到隊(duì)列中出現(xiàn)新的客戶端連接
agrv agrc參數(shù)的描述
###echo服務(wù)端 #include <stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h>#define BUF_SIZE 1024 void error_handling(char *message);int main(int argc,char *agrv[]) {int serv_sock,clnt_sock;char message[BUF_SIZE];int str_len,i;struct sockaddr_in serv_adr,clnt_adr;socklen_t clnt_adr_sz;if(argc!=2){printf("Usage : %s <PORT>\n", agrv[0]);exit(1);}serv_sock=socket(PF_INET,SOCK_STREAM,0);if(serv_sock==-1)error_handling("socket() error");memset(&serv_adr,0,sizeof(serv_adr));serv_adr.sin_family=AF_INET;serv_adr.sin_addr.s_addr=htonl(INADDR_ANY);serv_adr.sin_port=htons(atoi(agrv[1]));if(bind(serv_sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1)error_handling("bind() error");if(listen(serv_sock,5)==-1)error_handling("listen() error");clnt_adr_sz=sizeof(clnt_adr);for(int i=0; i<5; i++){clnt_sock=accept(serv_sock,(struct sockaddr*)&clnt_adr,&clnt_adr_sz);if(clnt_sock==-1)error_handling("accept() error");elseprintf("Connected client %d \n",i+1);while((str_len=read(clnt_sock,message,BUF_SIZE))!=0)write(clnt_sock,message,str_len);close(clnt_sock);}close(serv_sock);return 0; } void error_handling(char *message) {fputs(message,stderr);fputc('\n',stderr);exit(1); }
gcc編譯顯示警告
第五章 基于TCP的服務(wù)器端/客戶端(2)
##完美的回聲客戶端 #include <stdio.h> #include<stdlib.h> #include<string.h> #include<unistd.h> #include<arpa/inet.h> #include<sys/socket.h>#define BUF_SIZE 1024 void error_handling(char *message);int main(int argc,char *agrv[]) {int sock;char message[BUF_SIZE];int str_len,recv_len,recv_cnt;struct sockaddr_in serv_adr;if(argc!=3){printf("Usage : %s <IP> <PORT>\n", agrv[0]);exit(1);}sock=socket(PF_INET,SOCK_STREAM,0);if(sock==-1)error_handling("socket() error");memset(&serv_adr,0,sizeof(serv_adr));serv_adr.sin_family=AF_INET;serv_adr.sin_addr.s_addr=inet_addr(agrv[1]);serv_adr.sin_port=htons(atoi(agrv[2]));if(connect(sock,(struct sockaddr*)&serv_adr,sizeof(serv_adr))==-1)error_handling("connect() error");elseputs("Connected............");while(1){fputs("Input message(Q to quit): ",stdout);fgets(message,BUF_SIZE,stdin);if(!strcmp(message,"q\n")||!strcmp(message,"Q\n"))break;str_len=write(sock,message,strlen(message));recv_len=0;while(recv_len<str_len){recv_cnt=read(sock,message,BUF_SIZE-1);if(recv_cnt==-1)error_handling("read() error");recv_len+=recv_cnt;}message[str_len]=0;printf("Message from server: %s",message);}close(sock);return 0; } void error_handling(char *message) {fputs(message,stderr);fputc('\n',stderr);exit(1); }- I/O緩沖在每個(gè)TCP套接字中單獨(dú)存在;I/O緩沖在創(chuàng)建套接字時(shí)自動(dòng)生成;即使關(guān)閉套接字也會(huì)繼續(xù)傳遞輸入緩沖中遺留的數(shù)據(jù);關(guān)閉套接字將丟失輸入緩沖中的數(shù)據(jù)
- TCP中因?yàn)門CP會(huì)控制數(shù)據(jù)流(Sliding Window協(xié)議),不會(huì)發(fā)生超過(guò)輸入緩沖大小的傳輸數(shù)據(jù)
- write函數(shù)并不會(huì)在完成向?qū)Ψ街鳈C(jī)的數(shù)據(jù)傳輸時(shí)返回,而是在數(shù)據(jù)移到輸出緩沖時(shí),但TCP會(huì)保證對(duì)輸出緩沖數(shù)據(jù)的傳輸
第六章 基于UDP的服務(wù)器端/客戶端
- UDP提供不可靠的數(shù)據(jù)傳輸服務(wù),在重視性能而非可靠性的情況下,UDP是一種很好的選擇
- UDP最重要的作用就是根據(jù)端口號(hào)將傳到主機(jī)的數(shù)據(jù)包交付給最終的UDP套接字,TCP中套接字是一對(duì)一的關(guān)系,而UDP每方只需要一個(gè),收發(fā)信件的郵箱可以比喻成UDP套接字
- UDP存在數(shù)據(jù)邊界,一個(gè)數(shù)據(jù)包即可成為一個(gè)完整數(shù)據(jù),UDP通信過(guò)程中使用I/O函數(shù)調(diào)用次數(shù)應(yīng)保持一致
- 通過(guò)sendto傳遞數(shù)據(jù)分為3個(gè)階段:1.向UDP套接字注冊(cè)目標(biāo)IP和端口號(hào);2.傳輸數(shù)據(jù);3.刪除UDP套接字中注冊(cè)的目標(biāo)地址信息。這種未注冊(cè)目標(biāo)地址信息的套接字稱為未連接套接字,與此相對(duì)的還有已連接套接字(可以避免了1,3階段的過(guò)程)
- 創(chuàng)建已連接UDP套接字:connect(sock,(struct sockaddr*)&adr,sizeof(adr))就是調(diào)用了connect函數(shù),向UDP套接字注冊(cè)目標(biāo)IP和端口信息,注冊(cè)后可以使用write,read和sendto,recvfrom
第七章 優(yōu)雅地?cái)嚅_套接字連接
- TCP的半關(guān)閉:兩臺(tái)主機(jī)通過(guò)套接字建立連接后進(jìn)入可交換數(shù)據(jù)的狀態(tài),又稱“流形成的狀態(tài)”,此時(shí)有I/O流1和I/O流2,close函數(shù)會(huì)同時(shí)斷開這兩個(gè)流,不夠優(yōu)雅(發(fā)送完數(shù)據(jù)可能就調(diào)用close函數(shù),而此時(shí)可能還有對(duì)面發(fā)過(guò)來(lái)讓你必須接收的數(shù)據(jù),這種數(shù)據(jù)就被損毀了)
- 服務(wù)器端向客戶端傳送文件時(shí),客戶端不知道要接收到什么時(shí)候,也不能一直調(diào)用read函數(shù)(會(huì)阻塞),所以約定一個(gè)EOF標(biāo)志文件傳輸結(jié)束
第八章 域名及網(wǎng)絡(luò)地址
- DNS將域名轉(zhuǎn)換為IP
- IP地址比域名發(fā)生變更的概率更高,用域名比較好一些
- 對(duì)于上面的h_addr_list,他指向字符串指針數(shù)組,但字符串指針數(shù)組中的元素實(shí)際指向的是(實(shí)際保存的是)in_addr結(jié)構(gòu)體變量地址值;這里面用char **是因?yàn)樗鼮槎嚅T協(xié)議所用,指針類型不確定,而當(dāng)時(shí)又沒(méi)有void *,就用char *表示無(wú)法確定的指針類型
第九章 套接字的多種可選項(xiàng)
int getsockopt(int sock,int level, int optname, void *optval,socklen_t *optlen); ##optval為保存查看結(jié)果的緩沖地址值;optlen保存通過(guò)第四個(gè)參數(shù)返回的可選項(xiàng)信息的字節(jié)數(shù) int setsockopt(int sock,int level,int optname,const void* optval,socklen_t optlen); ##level為協(xié)議層;optval為可選項(xiàng)名- 一些常用的選項(xiàng):SO_SNDBUF&SO_RCVBUF;SO_REUSEADDR;TCP_NODELAY
- Nagle算法:p150,TCP套接字默認(rèn)使用Nagle算法交換數(shù)據(jù),網(wǎng)絡(luò)流量未受到太大影響時(shí),不使用Nagle算法要比使用它時(shí)傳輸速度更快(如傳輸大文件數(shù)據(jù));未準(zhǔn)確判斷數(shù)據(jù)特性時(shí)不應(yīng)禁用Nagle算法
總結(jié)
以上是生活随笔為你收集整理的TCP/IP网络编程复习(上)的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: Android卡顿检测及优化
- 下一篇: GP232RL与FT232RL操作区别