日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

网络编程实战

發布時間:2023/12/20 编程问答 25 豆豆
生活随笔 收集整理的這篇文章主要介紹了 网络编程实战 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

以下內容源于朱有鵬嵌入式課程的學習整理,如有侵權,請告知刪除。

目錄

一、Linux網絡編程框架

1、OSI參考模型

2、TCP/IP協議引入

3、BS和CS

二、TCP協議的學習1

1、關于TCP理解的重點

2、TCP如何保證可靠傳輸

三、TCP協議的學習2

1、TCP建立連接時的三次握手

2、TCP釋放連接時的四次握手

3、基于TCP通信的服務模式(編程時也是按這個模式編寫的)

4、常見的使用TCP協議的網絡應用

四、socket編程接口(與網絡通信相關的API)介紹

1、建立連接

2、發送和接收

3、輔助性函數

4、表示IP地址相關數據結構

五、IP地址格式轉換函數實踐

六、soekct實踐編程1_2

1、服務器端程序編寫

2、客戶端程序編寫

七、socket實踐編程3

八、socket編程實踐4

九、代碼


?

一、Linux網絡編程框架

1、OSI參考模型

(1)OSI 7層模型;

(2)網絡為什么要分層?

(3)網絡分層的具體表現。

2、TCP/IP協議引入

參閱博客:http://www.cnblogs.com/BlueTzar/articles/811160.html

(1)TCP/IP協議是用的最多的網絡協議實現;

(2)TCP/IP分為4層,對應OSI的7層;

(3)編程時最關注應用層,了解傳輸層,網際互聯層和網絡接入層不用管。

3、BS和CS

(1)CS架構介紹(client server,客戶端服務器架構);

(2)BS架構介紹(broswer server,瀏覽器服務器架構);

?

二、TCP協議的學習1

1、關于TCP理解的重點

(1)TCP協議工作在傳輸層,對上服務socket接口(與網絡通信有關的API),對下調用IP層;

(2)TCP協議面向連接,通信前必須先3次握手建立連接關系后才能開始通信;

(3)TCP協議提供可靠傳輸,有反饋機制,不怕丟包、亂序等。

2、TCP如何保證可靠傳輸

(1)TCP在傳輸有效信息前,要求通信雙方必須先握手,建立連接才能通信

(2)TCP的接收方收到數據包后會ack給發送方,若發送方未收到ack會丟包重傳

(3)TCP的有效數據內容會附帶校驗,以防止內容在傳遞過程中損壞;

(4)TCP會根據網絡帶寬來自動調節適配速率(滑動窗口技術);

(5)發送方會給各分割報文編號,接收方會校驗編號,一旦順序錯誤即會重傳。

(7)這些都是別人已經實現的功能,我們只需知道這些特性就可以了,編程時不會在意這些細節。

?

三、TCP協議的學習2

1、TCP建立連接時的三次握手

(1)建立連接需要三次握手;

(2)建立連接的條件:服務器處于listen狀態時(比如服務器在維護時,就不處在監聽狀態),客戶端主動發起connect;

2、TCP釋放連接時的四次握手

(1)關閉連接需要四次握手;

(2)服務器或者客戶端都可以主動發起關閉;

(4)這些握手協議已經封裝在TCP協議內部,socket編程接口平時不用管。

?

3、基于TCP通信的服務模式(編程時也是按這個模式編寫的)

(1)具有公網IP地址的服務器(或者使用動態IP地址映射技術);

(2)服務器端socket、bind、listen后處于監聽狀態;

(3)客戶端socket后,直接connect去發起連接。

(4)服務器收到并同意客戶端接入后,會建立TCP連接,然后雙方開始收發數據,收發時是雙向的,而且雙方均可發起。

(5)雙方均可發起關閉連接。

?

4、常見的使用TCP協議的網絡應用

(1)http、ftp;

(2)QQ服務器;

(3)mail服務器;

?

四、socket編程接口(與網絡通信相關的API)介紹

1、建立連接

(1)socket

  • socket函數類似于open,用來打開一個網絡連接,如果成功則返回一個網絡文件描述符(int類型)。
  • 對網絡連接進行操作,都是通過這個網絡文件描述符進行:發送相當于寫文件,接收相當于讀文件。
  • 函數參數見上圖標注,編程中的一個實例:socket(AF_INET,SOCK_STREAM,0)

(2)bind

(3)listen

(4)connect

?

2、發送和接收

(1)send和write:發送的時候可以使用write,也可以使用send,只是send多了一個flag。

(2)recv和read:和上述一樣。

?

3、輔助性函數

用來進行ip地址轉換的,點分十進制和二進制之間轉換

(1)inet_aton、inet_addr、inet_ntoa(以前使用的,不支持IPV6)

(2)inet_ntop、inet_pton(現在推薦使用的,支持IPV6/4)

?

4、表示IP地址相關數據結構

(1)都定義在 netinet/in.h;

(2)struct sockaddr

  • 是linux的網絡編程接口中用來表示IP地址的標準結構體,bind、connect等函數中都需要這個結構體,兼容IPV4和IPV6的。
  • 在實際編程中,會被一個struct sockaddr_in或者一個struct sockaddr_in6所填充。即它是一個形參,傳ruct sockaddr_in或者struct sockaddr_in6都可以。

(3)struct sockaddr_in

  • 注意里面包含了ip地址和端口號
struct sockaddr_in{__SOCKADDR_COMMON (sin_);in_port_t sin_port; /* Port number. */struct in_addr sin_addr; /* Internet address. *//* Pad to size of `struct sockaddr'. */unsigned char sin_zero[sizeof (struct sockaddr) -__SOCKADDR_COMMON_SIZE -sizeof (in_port_t) -sizeof (struct in_addr)];};

(4)struct in_addr

struct in_addr {in_addr_t s_addr; };

(5)typedef uint32_t in_addr_t

  • 網絡內部用來表示IP地址;

?

五、IP地址格式轉換函數實踐

1、inet_addr、inet_ntoa、inet_aton;(只能IPV4)

?

?

  • 從上面可知,存在大小端問題。解決方法:網絡字節序,其實就是統一使用大端模式。
  • 如果電腦使用的是小端模式,先把ip地址轉換為大端模式;如果本來就是大端模式,那就不用改。
  • 這些API會自動完成這樣的功能,即會檢測所用的電腦的模式,然后在代碼內部進行處理,最后輸出一定是大端模式的。

2、inet_pton、inet_ntop(可以用于IPV6)

  • 例一

?

  • 例二

?

六、soekct實踐編程1_2

結合代碼來看過程、參數含義

1、服務器端程序編寫

(1)socket

(2)bind

(3)listen

(4)accept,返回值是一個fd

  • 如果accept正確返回,則表示服務器和客戶端成功建立一個TCP連接
  • 可以通過該TCP連接與客戶端進行讀寫操作。
  • 而讀寫操作需要一個fd,此fd由accept返回。
  • socket返回的fd叫做監聽fd,是用來監聽客戶端的,不能用來和任何客戶端進行讀寫;
  • accept返回的fd叫做連接fd,用來和客戶端程序進行讀寫。

2、客戶端程序編寫

(1)socket

(2)connect

  • 端口號,實質就是一個數字編號,用來唯一地標識一個能上網的進程。
  • 端口號和IP地址,會被打包到當前進程發出的或者接收到的每個數據包。
  • 每個數據包將來在網絡上傳遞的時候,內部都包含了發送方和接收方的信息(就是IP地址和端口號)。

?

七、socket實踐編程3

1、客戶端發送&服務器接收

2、服務器發送&客戶端接收

3、探討:如何讓服務器和客戶端好好溝通

(1)客戶端和服務器原則上都可以任意的發和收,但是實際上雙方必須配合:client發的時候server就收,而server發的時候client就收;

(2)必須了解到的一點:client和server之間的通信是異步的,這就是問題的根源

(3)解決方案:依靠應用層協議來解決,即server和client事先做好一系列的通信約定。

?

八、socket編程實踐4

1、自定義應用層協議第一步:規定發送和接收方法

(1)規定連接建立后,由客戶端主動向服務器發出1個請求數據包,然后服務器收到數據包后回復客戶端一個回應數據包,這就是一個通信回合;

(2)整個連接的通信就是由N多個回合組成的。

2、自定義應用層協議第二步:定義數據包格式。

3、常用應用層協議:http、ftp……

4、UDP簡介

?

九、代碼

1、運行步驟

(1)將下面的這兩份代碼復制到linux下,形成兩份文檔client.c和server.c,然后gcc編譯

(2)修改linux的ip地址為192.168.1.141

(3)先運行server.c生成的可執行文件,再運行client.c生成的可執行文件。

2、代碼與邏輯

服務器

socket函數,獲取網絡連接的文件描述符
bind函數,將服務器的端口、ip地址與socket函數創建的文件描述符綁定
listen函數,監聽服務器的當前端口(其他端口不監聽)
accept函數,阻塞以等待用戶連接

客服端
socket函數,獲取網絡連接的文件描述符
connect函數,連接服務器
---連接上之后--
send函數,客服端給服務器發送數據
recv函數,客服端接收服務器的回復

client

#include<stdio.h> #include<sys/socket.h> #include<sys/types.h> #include<arpa/inet.h> #include<string.h>#define SERPORT 6013 #define SERADDR "192.168.1.141"//要設置為服務器的IP地址 #define CMD_REGISTER 1#define STAT_OK 0 #define STAT_ERR 1typedef struct FORMAT {char name[20];int age;int cmd;int stat; }info;char sendbuf[100]; char recvbuf[100];int main(void) {//第一步:socket函數,獲取網絡連接的文件描述符int sockfd=-1;int ret=-1;struct sockaddr_in seraddr={0};sockfd=socket(AF_INET,SOCK_STREAM,0);if(-1==sockfd){perror("socket error:");return -1;}printf("socket success.socket=%d.\n",sockfd);//第二步:connect函數,連接服務器seraddr.sin_family=AF_INET;//定義ip類型,IPV4還是IPV6seraddr.sin_port=htons(SERPORT);seraddr.sin_addr.s_addr=inet_addr(SERADDR);ret=connect(sockfd,(const struct sockaddr*)&seraddr,sizeof(seraddr));printf("連接成功\n");/* while(1){ //第三步:send函數,客戶端給服務器發送信息printf("請輸入你想發給服務器的內容:\n");scanf("%s",sendbuf);ret=send(sockfd,sendbuf,strlen(sendbuff),0);//第四步:客戶端接收服務器端的回復memset(recvbuf,0,sizeof(recvbuf));ret=recv(sockfd,recvbuf,sizeof(recvbuf),0);printf("服務器回復內容是:%s\n",recvbuf);//第五步:客戶端解釋服務器的回復,再做下一步定奪} */ info st1;while(1){ printf("\n請輸入學生姓名:\n");scanf("%s",st1.name);printf("\n請輸入學生年齡:\n");scanf("%d",&st1.age);st1.cmd=CMD_REGISTER;ret=send(sockfd,&st1,sizeof(info),0);//第四步:客戶端接收服務器端的回復memset(&st1,0,sizeof(st1));ret=recv(sockfd,&st1,sizeof(st1),0);if(STAT_OK==st1.stat){printf("注冊學生信息成功!");}elseprintf("注冊學生信息失敗!");}return 0; }

server:

#include <stdio.h> #include <arpa/inet.h> #include <string.h> #include <sys/types.h> /* See NOTES */ #include <sys/socket.h>#define MYPORT 6013 #define SERADDR "192.168.1.141"//要設置為服務器的IP地址 #define BLEN 100 #define STAT_OK 0 #define STAT_ERR 1 #define CMD_REGISTER 1 typedef struct FORMAT {char name[20];int age;int cmd;int stat; }info;char recvbuf[100];int main(void) {int sockfd=-1;int ret=-1;int clifd=-1;socklen_t len=0;struct sockaddr_in seraddr={0};//也可以使用memset函數進行初始化struct sockaddr_in clientaddr={0};//第一步:socket函數,獲取網絡連接的文件描述符sockfd=socket(AF_INET,SOCK_STREAM,0);if(-1==sockfd){perror("socket error:");return -1;}printf("socket success!socket=%d.\n",sockfd);//第二步:bind函數,綁定sockfd與服務器的ip地址、端口號//填充seraddr這個結構體seraddr.sin_family=AF_INET;//定義ip類型,IPV6還是IPV4seraddr.sin_port=htons(MYPORT);seraddr.sin_addr.s_addr=inet_addr(SERADDR);ret=bind(sockfd,(const struct sockaddr*)&seraddr,sizeof(seraddr));//類型不一樣,會警告if(ret==-1){perror("bind error:");//函數本身有錯誤號時可以用perror來顯示錯誤信息}printf("bind success!\n");//第三步:listen函數,監聽服務器的當前端口(其他端口不監聽)ret=listen(sockfd,BLEN);//第二個參數是服務器允許的隊列長度,比如最多100號if(ret==-1){perror("listen error:");}printf("listen success!\n");//第四步:accept函數,阻塞等待用戶連接 //注意accept返回值是網絡文件描述符,和sockfd不同,它才是真正的用于發送數據的fd,而sockfd只是用于偵聽的。clifd=accept(sockfd,(struct sockaddr*)&clientaddr,&len);printf("用戶連接成功!\n");/* while(1){//第五步:recv函數,服務器開始接收數據ret=recv(clifd,recvbuf,sizeof(recvbuf),0);printf("client發送的內容是:%s\n",recvbuf);memset(recvbuf,0,sizeof(recvbuf));//第六步:服務器解釋數據包//第七步:回復客戶端OKret=send(clifd,"OK",2,0);} */while(1){info st;ret=recv(clifd,&st,sizeof(recvbuf),0);if(CMD_REGISTER==st.cmd){printf("用戶要注冊學生信息\n");printf("姓名:%s,年齡:%d\n",st.name,st.age);st.stat=STAT_OK;ret=send(clifd,&st,sizeof(info),0);}}return 0; }

?

總結

以上是生活随笔為你收集整理的网络编程实战的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。