Windows网络编程初步
1. OSI/RM和TCP/IP
國際標準化組織(ISO)和國際電報電話咨詢委員會(CCITT)制定OSI/RM
OSI/RM:Open SystemInterconnect/Recommended Model
圖1OSI/RM和TCP/IP體系結構模型
l? TCP: Transmission Control Protocol 傳輸控制協議是一種面向連接的、可靠的、基于字節流的傳輸層通信協議。
l? Internet Protocol網際協議:IP不提供可靠的傳輸服務,它不提供端到端的或(路由)結點到(路由)結點的確認,對數據沒有差錯控制,它只使用報頭的校驗碼,它不提供重發和流量控制。如果出錯可以通過ICMP報告,ICMP在IP模塊中實現。
圖2? TCP/IP協議棧
TD-SCDMA:Time Division-Synchronous Code Division Multiple Access(時分同步碼分多址)中國制定的一個3G通信標準。
2.套接字
2.1套接字編程接口的起源與發展
2.2套接字的含義與分類
2.3套接字接口的位置及實現方式
端口號port:16位無符號二進制整數0~65535。
進程網絡地址:三元組(傳輸協議、主機IP地址、端口號)
一對通信進程:五元組(傳輸層協議、本地主機IP、本地傳輸層端口號、遠端主機IP、遠端傳輸層端口號)
套接字:TCP用主機的IP地址加上主機上的端口號作為TCP連接的端點,這種端點就叫做套接字(socket)或插口。套接字用(IP地址:端口號)表示。
套接字是網絡通信過程中端點的抽象表示,包含進行網絡通信必需的五種信息(五元組):連接使用的協議,本地主機的IP地址,本地進程的協議端口,遠地主機的IP地址,遠地進程的協議端口。
關鍵詞:網絡應用程序編程接口-套接字、系統調用、Berkeley Sockets、Windows Sockets、
套接字的含義、套接字的分類、套接字接口的位置及實現方式
套接字本質上是一種應用程序調用操作系的網絡通信功能的系統調用接口。
套接字的分類:
1)?????流式套接字(Stream Socket)
2)?????數據報套接字(Datagram Socket):TCP
3)?????原始套接字(Raw Socket):UDP
3.網絡編程的不同層次
4.WinSock編程初步
應用程序調用WinSock API函數實現相互之間的通信,而WinSock API函數又利用下層的Windows操作系統中的網絡通信協議和相關的系統調用實現其通信功能。WinSock與網絡應用程序和操作系統中的網絡通信協議軟件之間的關系見圖3.1。
4.1DLL常識
4.2WinSock編程初步示例
表1常用協議及協議號
協議名 | 協議號 |
IP | 0 |
ICMP | 1 |
TCP | 6 |
UDP | 17 |
WinSock提供了getprotobyname()和getprotobyname()來完成協議名字和編號之間的轉換
以下代碼實現:顯示因特網所有協議的名稱以及相應的協議號
#include "stdafx.h" //1.包含WinSock頭我文件:#include"WinSock2.h" #include"WinSock2.h" #include<iostream> //2.鏈接WinSock導入庫:#pragma comment(lib,"ws2_32.lib") #pragma comment(lib,"ws2_32.lib") using namespace std;int _tmain(int argc, _TCHAR* argv[]) {WSADATA wsaData;WORD wVersionRequested = MAKEWORD(2, 2); //3.加載WinSock動態鏈接庫if (WSAStartup(wVersionRequested, &wsaData) != 0){cout << "加載WinSock DLL失敗!\n";return 0;}struct protoent* pProto;for (int i = 1; i < 256; i++){if ((pProto = getprotobynumber(i)) != NULL){cout << "協議號:" << pProto->p_name << endl;cout << "協議號:" << pProto->p_proto << endl;}} //4.注銷WinSock動態鏈接庫WSACleanup();system("pause");return 0; }
在VC中使用WinSock,以下四步必不可少:
1.?????包含WinSock頭我文件:#include"WinSock2.h"
2.?????鏈接WinSock導入庫:#pragma comment(lib,"ws2_32.lib")
3.?????加載WinSock動態鏈接庫
4.?????注銷WinSock動態鏈接庫
4.3WinSock網絡地址表示
4.4地址結構
4.4.1 in_addr結構
用于存儲一個IPv4地址。
共用體類型的字段S_un,專門用來存儲32位的IP地址。
4.4.2 sockaddr_in結構
該結構對IP地址和協議號進行了封裝。
// // IPv4 Socket address, Internet style //typedef struct sockaddr_in {#if(_WIN32_WINNT < 0x0600)short sin_family; //地址族,IP協議地址對應的值為AF_INET #else //(_WIN32_WINNT < 0x0600)ADDRESS_FAMILY sin_family; #endif //(_WIN32_WINNT < 0x0600)USHORT sin_port; //16位端口號IN_ADDR sin_addr; //32位IP地址,使用網絡字節順序(大端序)CHAR sin_zero[8]; } SOCKADDR_IN, *PSOCKADDR_IN;
4.4.3 sockaddr結構
sockaddr為通用套接字地址結構。當使用TCP/IP時,該結構內容與sockaddr_in完全相同。
//sockaddr_in結構與sockaddr結構存儲內容完全一致。因此:struct sockaddr a;struct sockaddr_in* p;p = (sockaddr_in*)&a;p->sin_family = AF_INET;p->sin_port = 54321; p->sin_addr.S_un.S_addr = inet_addr("192.168.1.1");
以上三個地址結構體的內存大小:
sizeof(in_addr)=4
sizeof(sockaddr_in)=16
sizeof(sockaddr)=16
(考慮結構體內存對齊)
4.5 IP地址轉換函數
4.5.1 inet_addr函數
unsigned?long inet_addr(constchar* cp);
cp指向點分十進制字符串,返回無符號長整型32位二進制的網絡字節順序的IP地址
4.5.2 inet_aton函數
將參數cp指向的點分十進制表示的IP地址字符串轉換為32位無符號長整型數,并存放于參數inp指向的in_addr結構變量中。
int inet_aton(constchar* cp, structin_addr* inp);
4.5.3 inet_ntoa函數
將一個包含在in_addr結構變量中的長整型IP地址轉換為點分點分十進制形式。
char* inet_ntoa(structin_addr in);
函數調用成功則返回一個字符指針,該指針指向一個char型緩沖區,該緩沖區保存有由參數in的值轉換而來的點分十進制表示的IP地址字符串。調用失敗則返回NULL指針。
4.6 WinSock錯誤處理
int WSAGetLastError(void);
函數返回上一次WinSoc函數調用錯誤時返回的錯誤碼。
4.7網絡字節順序
計算機在存儲多字節數據時存在大端順序(Big Endian)和小端順序(Little Endian)。
對于字符編碼,編碼標準中明確規定了字節順序。但對于整數數據則不存在類似的規定。
字節的高位與低位:
舉個例子,int a = 0x12345678 ; 那么左邊12就是高位字節,右邊的78就是低位字節,從左到右,由高到低。int b=0x1234:12是高字節,34是低字節。
地址的高端與低端
0x00000001
0x00000002
0x00000003
0x00000004
從上倒下,由低到高,地址值小的為低端地址,地址值大的為高端地址。
?
Bit-endian 如此存放(按原來順序存儲,書寫順序)
0x00000001?????????? -- 12
0x00000002?????????? -- 34
0x00000003?????????? -- 56
0x00000004?????????? -- 78
?
Little-endian 如此存放(高字節存高地址,低字節存低地址)
0x00000001?????????? -- 78
0x00000002?????????? -- 56
0x00000003?????????? -- 34
0x00000004?????????? -- 12
4.7.1 htons函數
該函數將一個16位的無符號短整型數據由主機字節順序轉換為網絡字節順序。
u_short htons(u_short hostshort);
4.7.2 ntohs函數
該函數將一個16位的無符號短整型數據由網絡字節順序轉換為主機字節順序返回。
u_short ntohs(u_short netshort);
4.7.3 htonl函數
該函數將一個32位的無符號長整型數據由主機字節順序轉換為網絡字節順序返回。
u_long htonl(u_long hostlong);
4.7.4 ntohl函數
該函數將一個32位的無符號長整型數據由網絡字節順序轉換為主機字節順序并返回。
u_long ntohl(u_long netlong);
#include "stdafx.h" #include<iostream> #include"WinSock2.h" #pragma comment(lib,"ws2_32.lib")using namespace std;int _tmain(int argc, _TCHAR* argv[]) {WSADATA wsaData;WORD wVersionRequested = MAKEWORD(2, 2);if (WSAStartup(wVersionRequested, &wsaData) != 0){cout << "加載WinSock DLL失敗!\n";return 0;}u_short x, y = 0x1234;x = htons(y);cout << "主機字節順序:" << hex << y << "\t對應的網絡字節順序:" << x << endl;u_long a, b = 0x1122ABCD;a = htonl(b);cout << "主機字節順序:" << hex << b << "\t對應的網絡字節順序:" << a << endl;WSACleanup();system("pause");return 0; }/*主機字節順序:1234 對應的網絡字節順序:3412 主機字節順序:1122abcd 對應的網絡字節順序:cdab2211 */
4.7.5以上四個函數的WinSock版本
int WSAHtons(SOCKET s, u_short hostshort, u_short* lpnetshort);
WSAHtons將一個16位的無符號短整型數據由主機字節順序轉換為網絡字節順序。
?
??? int WSANtohs(SOCKET s, u_short netshort, u_short* lphostshort);
??? int WSAHtonl(SOCKET s, u_long hostlong, u_long* lpnetlong);
int WSANtohl(SOCKET s, u_long netlong, u_long* lphostlong);
4.8網絡配置信息查詢
4.8.1主機名字與IP地址查詢
4.8.2服務查詢
struct servent* getservbyname(const char* name, const char* proto);struct servent {char FAR * s_name; /* official service name */char FAR * FAR * s_aliases; /* alias list */#ifdef _WIN64char FAR * s_proto; /* protocol to use */short s_port; /* port # */#elseshort s_port; /* port # */char FAR * s_proto; /* protocol to use */#endif};struct servent* getservbyport(int port, const char* proto); WinSock提供的異步版本:HANDLE WSAAsyncGetServByName(HWND hWnd,unsigned int wMsg,const char FAR* name,const char FAR* proto,char FAR* buf,int buflen);HANDLE WSAAsyncGetServByPort(HWND hWnd,unsigned int wMsg,int port,const char* proto,char* buf,int buflen);
4.8.3協議查詢
struct protoent* getprotobyname(const char* name);struct protoent {char FAR * p_name; /* official protocol name */char FAR * FAR * p_aliases; /* alias list */short p_proto; /* protocol # */};struct protoent* getprotobynumber(int number); WinSock提供的異步版本:HANDLE WSAAsyncGetProtoByName(HWND hWnd,unsigned int wMsg,const char* name,char* buf,int buflen);HANDLE PASCAL FAR WSAAsyncGetProtoByNumber(HWND hWnd,unsigned int wMsg,int number,char FAR* buf,int buflen);總結
以上是生活随笔為你收集整理的Windows网络编程初步的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: nRF 51822 nRF52832固件
- 下一篇: Verilog数字系统基础设计-数据转换