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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

TCP/IP 网络数据封包和解包

發布時間:2025/4/14 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 TCP/IP 网络数据封包和解包 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

這是一個網上的代碼;下面列出資料并簡略分析代碼;


TCP/IP 網絡數據封包和解包?
.
?
TCP/IP 網絡數據以流的方式傳輸,數據流是由包組成,如何判定接收方收到的包是否是一個完整的包就要在發送時對包進行處理,這就是封包技術,將包處理成包頭,包體
?
包頭是包的開始標記,整個包的大小就是包的結束標記。接收方只要按同樣的方式解包即可,下面是一個網絡服務端和客戶端程序代碼。
?
客戶端和服務端共享的文件:(數據包的定義)?


01.#pragma once ?
02. ?
03. ?
04.#define NET_PACKET_DATA_SIZE 1024 ??
05.#define NET_PACKET_SIZE (sizeof(NetPacketHeader) + NET_PACKET_DATA_SIZE) * 10 ?
06. ?
07. ?
08./// 網絡數據包包頭 ?
09.struct NetPacketHeader ?
10.{ ?
11. ? ?unsigned short ? ? ?wDataSize; ?///< 數據包大小,包含封包頭和封包數據大小 ?
12. ? ?unsigned short ? ? ?wOpcode; ? ?///< 操作碼 ?
13.}; ?
14. ?
15./// 網絡數據包 ?
16.struct NetPacket ?
17.{ ?
18. ? ?NetPacketHeader ? ? Header; ? ? ? ? ? ? ? ? ? ? ? ? ///< 包頭 ?
19. ? ?unsigned char ? ? ? Data[NET_PACKET_DATA_SIZE]; ? ? ///< 數據 ?
20.}; ?
21. ?
22. ?
23. ?
24.// ?
25. ?
26. ?
27./// 網絡操作碼 ?
28.enum eNetOpcode ?
29.{ ?
30. ? ?NET_TEST1 ? ? ? ? ? = 1, ?
31.}; ?
32. ?
33./// 測試1的網絡數據包定義 ?
34.struct NetPacket_Test1 ?
35.{ ?
36. ? ?int ? ? nIndex; ?
37. ? ?char name[20]; ?
38. ? ?char sex[20]; ?
39. ? ?int age; ?
40. ? ?char ? ?arrMessage[512]; ?
41.}; ?




服務端:




[cpp] view plaincopyprint?
01.#pragma once ?
02. ?
03.class TCPServer ?
04.{ ?
05.public: ?
06. ? ?TCPServer(); ?
07. ? ?virtual ~TCPServer(); ?
08. ?
09.public: ?
10. ? ?void run(); ?
11. ?
12. ? ?/// 接受客戶端接入 ?
13. ? ?void acceptClient(); ?
14. ?
15. ? ?/// 關閉客戶端 ?
16. ? ?void closeClient(); ?
17. ?
18. ? ?/// 發送數據 ?
19. ? ?bool SendData(unsigned short nOpcode, const char* pDataBuffer, const unsigned int& nDataSize); ?
20. ?
21.private: ?
22. ? ?SOCKET ? ? ?mServerSocket; ?///< 服務器套接字句柄 ?
23. ? ?sockaddr_in mServerAddr; ? ?///< 服務器地址 ?
24. ?
25. ? ?SOCKET ? ? ?mAcceptSocket; ?///< 接受的客戶端套接字句柄 ?
26. ? ?sockaddr_in mAcceptAddr; ? ?///< 接收的客戶端地址 ?
27. ?
28. ? ?char ? ? ? ?m_cbSendBuf[NET_PACKET_SIZE]; ?
29.}; ?



[cpp] view plaincopyprint?
01.#include "stdafx.h" ?
02. ?
03. ?
04.TCPServer::TCPServer() ?
05.: mServerSocket(INVALID_SOCKET) ?
06.{ ?
07. ? ?// 創建套接字 ?
08. ? ?mServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); ?
09. ? ?if (mServerSocket == INVALID_SOCKET) ?
10. ? ?{ ?
11. ? ? ? ?std::cout << "創建套接字失敗!" << std::endl; ?
12. ? ? ? ?return; ?
13. ? ?} ?
14. ?
15. ? ?// 填充服務器的IP和端口號 ?
16. ? ?mServerAddr.sin_family ? ? ?= AF_INET; ?
17. ? ?mServerAddr.sin_addr.s_addr = INADDR_ANY; ?
18. ? ?mServerAddr.sin_port ? ? ? ?= htons((u_short)SERVER_PORT); ?
19. ?
20. ? ?// 綁定IP和端口 ?
21. ? ?if ( ::bind(mServerSocket, (sockaddr*)&mServerAddr, sizeof(mServerAddr)) == SOCKET_ERROR) ?
22. ? ?{ ?
23. ? ? ? ?std::cout << "綁定IP和端口失敗!" << std::endl; ?
24. ? ? ? ?return; ?
25. ? ?} ?
26. ?
27. ? ?// 監聽客戶端請求,最大同時連接數設置為10. ?
28. ? ?if ( ::listen(mServerSocket, SOMAXCONN) == SOCKET_ERROR) ?
29. ? ?{ ?
30. ? ? ? ?std::cout << "監聽端口失敗!" << std::endl; ?
31. ? ? ? ?return; ?
32. ? ?} ?
33. ?
34. ? ?std::cout << "啟動TCP服務器成功!" << std::endl; ?
35.} ?
36. ?
37.TCPServer::~TCPServer() ?
38.{ ?
39. ? ?::closesocket(mServerSocket); ?
40. ? ?std::cout << "關閉TCP服務器成功!" << std::endl; ?
41.} ?
42. ?
43.void TCPServer::run() ?
44.{ ?
45. ? ?// 接收客戶端的連接 ?
46. ? ?acceptClient(); ?
47. ?
48. ? ?int nCount = 0; ?
49. ? ?for (;;) ?
50. ? ?{ ?
51. ? ? ? ?if (mAcceptSocket == INVALID_SOCKET) ??
52. ? ? ? ?{ ?
53. ? ? ? ? ? ?std::cout << "客戶端主動斷開了連接!" << std::endl; ?
54. ? ? ? ? ? ?break; ?
55. ? ? ? ?} ?
56. ?
57. ? ? ? ?// 發送數據包 ?
58. ? ? ? ?NetPacket_Test1 msg;//消息類型 ?
59. ? ? ? ?msg.nIndex = nCount; ?
60. ? ? ? ?msg.age=23; ?
61. ? ? ? ?strncpy(msg.arrMessage, "北京市朝陽區", sizeof(msg.arrMessage) ); ?
62. ? ? ? ?strncpy(msg.name, "天策", sizeof(msg.name) ); ?
63. ? ? ? ?strncpy(msg.sex, "男", sizeof(msg.sex) ); ?
64. ?
65. ? ? ? ?bool bRet = SendData(NET_TEST1, (const char*)&msg, sizeof(msg));//強制類型轉換為字符串類型 ?
66. ? ? ? ?if (bRet) ?
67. ? ? ? ?{ ?
68. ? ? ? ? ? ?std::cout << "發送數據成功!" << std::endl; ?
69. ? ? ? ?} ?
70. ? ? ? ?else ?
71. ? ? ? ?{ ?
72. ? ? ? ? ? ?std::cout << "發送數據失敗!" << std::endl; ?
73. ? ? ? ? ? ?break; ?
74. ? ? ? ?} ?
75. ?
76. ? ? ? ?++nCount; ?
77. ? ?} ?
78.} ?
79. ?
80.void TCPServer::closeClient() ?
81.{ ?
82. ? ?// 判斷套接字是否有效 ?
83. ? ?if (mAcceptSocket == INVALID_SOCKET) return; ?
84. ?
85. ? ?// 關閉客戶端套接字 ?
86. ? ?::closesocket(mAcceptSocket); ?
87. ? ?std::cout << "客戶端套接字已關閉!" << std::endl; ?
88.} ?
89. ?
90.void TCPServer::acceptClient() ?
91.{ ?
92. ? ?// 以阻塞方式,等待接收客戶端連接 ?
93. ? ?int nAcceptAddrLen = sizeof(mAcceptAddr); ?
94. ? ?mAcceptSocket = ::accept(mServerSocket, (struct sockaddr*)&mAcceptAddr, &nAcceptAddrLen); ?
95. ? ?std::cout << "接受客戶端IP:" << inet_ntoa(mAcceptAddr.sin_addr) << std::endl; ?
96.} ?
97. ?
98.bool TCPServer::SendData( unsigned short nOpcode, const char* pDataBuffer, const unsigned int& nDataSize ) ?
99.{ ?
100. ? ?NetPacketHeader* pHead = (NetPacketHeader*) m_cbSendBuf; ?
101. ? ?pHead->wOpcode = nOpcode;//操作碼 ?
102. ?
103. ? ?// 數據封包 ?
104. ? ?if ( (nDataSize > 0) && (pDataBuffer != 0) ) ?
105. ? ?{ ?
106. ? ? ? ?CopyMemory(pHead+1, pDataBuffer, nDataSize); ??
107. ? ?} ?
108. ?
109. ? ?// 發送消息 ?
110. ? ?const unsigned short nSendSize = nDataSize + sizeof(NetPacketHeader);//包的大小事發送數據的大小加上包頭大小 ?
111. ? ?pHead->wDataSize = nSendSize;//包大小 ?
112. ? ?int ret = ::send(mAcceptSocket, m_cbSendBuf, nSendSize, 0); ?
113. ? ?return (ret > 0) ? true : false; ?
114.} ?


[cpp] view plaincopyprint?
01.// testTCPServer.cpp : 定義控制臺應用程序的入口點。 ?
02.// ?
03. ?
04.#include "stdafx.h" ?
05. ?
06. ?
07. ?
08.int _tmain(int argc, _TCHAR* argv[]) ?
09.{ ?
10. ? ?TCPServer server; ?
11. ? ?server.run(); ?
12. ?
13. ? ?system("pause"); ?
14. ? ?return 0; ?
15.} ?




客戶端:

[cpp] view plaincopyprint?
01.<span style="font-size: 14px;">#pragma once ?
02. ?
03.class TCPClient ?
04.{ ?
05.public: ?
06. ? ?TCPClient(); ?
07. ? ?virtual ~TCPClient(); ?
08. ?
09.public: ?
10. ? ?/// 主循環 ?
11. ? ?void run(); ?
12. ?
13. ? ?/// 處理網絡消息 ?
14. ? ?bool OnNetMessage(const unsigned short& nOpcode, ??
15. ? ? ? ?const char* pDataBuffer, unsigned short nDataSize); ?
16. ?
17. ? ?bool OnNetPacket(NetPacket_Test1* pMsg); ?
18. ?
19.private: ?
20. ? ?SOCKET ? ? ? ? ? ? ?mServerSocket; ?///< 服務器套接字句柄 ?
21. ? ?sockaddr_in ? ? ? ? mServerAddr; ? ?///< 服務器地址 ?
22. ?
23. ? ?char ? ? ? ? ? ? ? ?m_cbRecvBuf[NET_PACKET_SIZE]; ?
24. ? ?char ? ? ? ? ? ? ? ?m_cbDataBuf[NET_PACKET_SIZE]; ?
25. ? ?int ? ? ? ? ? ? ? ? m_nRecvSize; ?
26.}; ?
27.</span> ?


?

[cpp] view plaincopyprint?
01.#include "stdafx.h" ?
02. ?
03. ?
04. ?
05.TCPClient::TCPClient() ?
06.{ ?
07. ? ?memset( m_cbRecvBuf, 0, sizeof(m_cbRecvBuf) ); ?
08. ? ?m_nRecvSize = 0; ?
09. ?
10. ? ?// 創建套接字 ?
11. ? ?mServerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_IP); ?
12. ? ?if (mServerSocket == INVALID_SOCKET) ?
13. ? ?{ ?
14. ? ? ? ?std::cout << "創建套接字失敗!" << std::endl; ?
15. ? ? ? ?return; ?
16. ? ?} ?
17. ?
18. ? ?// 填充服務器的IP和端口號 ?
19. ? ?mServerAddr.sin_family ? ? ?= AF_INET; ?
20. ? ?mServerAddr.sin_addr.s_addr = inet_addr(SERVER_IP); ?
21. ? ?mServerAddr.sin_port ? ? ? ?= htons((u_short)SERVER_PORT); ?
22. ?
23. ? ?// 連接到服務器 ?
24. ? ?if ( ::connect(mServerSocket, (struct sockaddr*)&mServerAddr, sizeof(mServerAddr))) ?
25. ? ?{ ?
26. ? ? ? ?::closesocket(mServerSocket); ?
27. ? ? ? ?std::cout << "連接服務器失敗!" << std::endl; ?
28. ? ? ? ?return; ??
29. ? ?} ?
30.} ?
31. ?
32.TCPClient::~TCPClient() ?
33.{ ?
34. ? ?::closesocket(mServerSocket); ?
35.} ?
36. ?
37.void TCPClient::run() ?
38.{ ?
39. ? ?int nCount = 0; ?
40. ? ?for (;;) ?
41. ? ?{ ?
42. ? ? ? ?// 接收數據 ?
43. ? ? ? ?int nRecvSize = ::recv(mServerSocket, ?
44. ? ? ? ? ? ?m_cbRecvBuf+m_nRecvSize, ??
45. ? ? ? ? ? ?sizeof(m_cbRecvBuf)-m_nRecvSize, 0); ?
46. ? ? ? ?if (nRecvSize <= 0) ?
47. ? ? ? ?{ ?
48. ? ? ? ? ? ?std::cout << "服務器主動斷開連接!" << std::endl; ?
49. ? ? ? ? ? ?break; ?
50. ? ? ? ?} ?
51. ?
52. ? ? ? ?// 保存已經接收數據的大小 ?
53. ? ? ? ?m_nRecvSize += nRecvSize; ?
54. ?
55. ? ? ? ?// 接收到的數據夠不夠一個包頭的長度 ?
56. ? ? ? ?while (m_nRecvSize >= sizeof(NetPacketHeader))//已經收到一個完整的包,如果沒用收到一個完整的包,此處循環不執行,繼續下一輪循環 ?
57. ? ? ? ?{ ?
58. ? ? ? ? ? ?// 收夠5個包,主動與服務器斷開 ?
59. ? ? ? ? ? ?if (nCount >= 5) ?
60. ? ? ? ? ? ?{ ?
61. ? ? ? ? ? ? ? ?::closesocket(mServerSocket); ?
62. ? ? ? ? ? ? ? ?break; ?
63. ? ? ? ? ? ?} ?
64. ?
65. ? ? ? ? ? ?// 讀取包頭 ?
66. ? ? ? ? ? ?NetPacketHeader* pHead = (NetPacketHeader*) (m_cbRecvBuf); ?
67. ? ? ? ? ? ?const unsigned short nPacketSize = pHead->wDataSize; ?
68. ?
69. ? ? ? ? ? ?// 判斷是否已接收到足夠一個完整包的數據 ?
70. ? ? ? ? ? ?if (m_nRecvSize < nPacketSize) ?
71. ? ? ? ? ? ?{ ?
72. ? ? ? ? ? ? ? ?// 還不夠拼湊出一個完整包 ?
73. ? ? ? ? ? ? ? ?break; ?
74. ? ? ? ? ? ?} ?
75. ?
76. ? ? ? ? ? ?// 拷貝到數據緩存 ?
77. ? ? ? ? ? ?CopyMemory(m_cbDataBuf, m_cbRecvBuf, nPacketSize); ?
78. ?
79. ? ? ? ? ? ?// 從接收緩存移除 ?
80. ? ? ? ? ? ?MoveMemory(m_cbRecvBuf, m_cbRecvBuf+nPacketSize, m_nRecvSize); ?
81. ? ? ? ? ? ?m_nRecvSize -= nPacketSize; ?
82. ?
83. ? ? ? ? ? ?// 解密數據,以下省略一萬字 ?
84. ? ? ? ? ? ?// ... ?
85. ?
86. ? ? ? ? ? ?// 分派數據包,讓應用層進行邏輯處理 ?
87. ? ? ? ? ? ?pHead = (NetPacketHeader*) (m_cbDataBuf); ?
88. ? ? ? ? ? ?const unsigned short nDataSize = nPacketSize - (unsigned short)sizeof(NetPacketHeader); ?
89. ? ? ? ? ? ?OnNetMessage(pHead->wOpcode, m_cbDataBuf+sizeof(NetPacketHeader), nDataSize); ?
90. ?
91. ? ? ? ? ? ?++nCount; ?
92. ? ? ? ?} ?
93. ? ?} ?
94. ?
95. ? ?std::cout << "已經和服務器斷開連接!" << std::endl; ?
96.} ?
97. ?
98.bool TCPClient::OnNetMessage( const unsigned short& nOpcode, ??
99. ? ? ? ? ? ? ? ? ? ? ? ? ? ? const char* pDataBuffer, unsigned short nDataSize ) ?
100.{ ?
101. ? ?switch (nOpcode) ?
102. ? ?{ ?
103. ? ?case NET_TEST1: ?
104. ? ? ? ?{ ?
105. ? ? ? ? ? ?NetPacket_Test1* pMsg = (NetPacket_Test1*) pDataBuffer; ?
106. ? ? ? ? ? ?return OnNetPacket(pMsg); ?
107. ? ? ? ?} ?
108. ? ? ? ?break; ?
109. ?
110. ? ?default: ?
111. ? ? ? ?{ ?
112. ? ? ? ? ? ?std::cout << "收取到未知網絡數據包:" << nOpcode << std::endl; ?
113. ? ? ? ? ? ?return false; ?
114. ? ? ? ?} ?
115. ? ? ? ?break; ?
116. ? ?} ?
117.} ?
118. ?
119.bool TCPClient::OnNetPacket( NetPacket_Test1* pMsg ) ?
120.{ ?
121. ? ?std::cout << "索引:" << pMsg->nIndex << " ?字符串:" << pMsg->arrMessage <<"name:"<<pMsg->name<<"sex:"<<pMsg->sex<<"age:"<<pMsg->age<< std::endl; ?
122. ? ?return true; ?
123.} ?


[cpp] view plaincopyprint?
01.#include "stdafx.h" ?
02. ?
03. ?
04.int _tmain(int argc, _TCHAR* argv[]) ?
05.{ ?
06. ? ?TCPClient client; ?
07. ? ?client.run(); ?
08. ?
09. ? ?system("pause"); ?
10. ? ?return 0; ?
11.} ?




下面分析一下其代碼;
首先這是一個VC++程序;因為,_tmain是VC++下的類似于C的main的東東;


首先定義包頭結構體,包結構體,操作碼枚舉;


首先運行客戶端;在客戶端的構造函數中,分配接收緩沖區,創建套接字,連接服務器;
run()函數運行,接收并保存包,調用OnNetMessage()進行處理;
OnNetMessage()中,如果nOpcode是NET_TEST1,調用OnNetPacket();
OnNetPacket()中輸出包的內容;


服務端的構造函數,創建套接字,綁定IP和端口,監聽客戶端請求;
run()中,接收客戶端連接,發送數據包;
服務端也是一個單獨的控制臺應用程序;單獨啟動;







《新程序員》:云原生和全面數字化實踐50位技術專家共同創作,文字、視頻、音頻交互閱讀

總結

以上是生活随笔為你收集整理的TCP/IP 网络数据封包和解包的全部內容,希望文章能夠幫你解決所遇到的問題。

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