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