第1章 Winsock簡介

來源:互聯網
上載者:User

Microsoft Windows網路編程第2版    楊合慶 譯         清華大學出版社

對應的英文書名:Network Programming for Microsoft Windows 2nd

1 winsock是網路介面,不是協議。

2 Winsock有1和2兩個版本,通過函數首碼WSA可以區分,Winsock2函

  數前有WSA首碼。但有幾個例外WSAStartup、WSACleanup、WSARecvEx、

  WSAGetLastError屬於1.1規範。

3 WinCE只支援Winsock1

      winsock1   winsock.h      wsock32.lib

      winsock2   winsock2.h     ws2_32.lib

      編程擴充   mswsock.h      mswsock.dll

4 使用WSAStartup進行Winsock初始化,具體用法見MSDN和書本

  結束時使用WSACleanup釋放由Winsock分配資源,也可以讓作業系統自動

  釋放,但這不符合Winsock規範。

5 SOCKADDR_IN用來指定IP和連接埠號碼用

  struct sockaddr_in {

    short sin_family;           // 必須為AF_INET

    unsigned short sin_port;    // 連接埠號碼

    struct in_addr sin_addr;    // IP,可用inet_add(char* )得IP

    char sin_zero[8];           // 填充,使其與SOCKADDR結構長度一樣

  };

6 Inter86處理器上,多位元組是小端(little-endian),Internet連網標準的字

  節序是大端模式(big-endian),稱為網路位元組序(network-byte)。

  主機位元組序轉網路位元組序函數

        htonl、WSAHtonl、htons、WSAHtons

  網路位元組序轉主機位元組序

        ntohl、WSANtohl、ntohs、WSANtohs

7 建立通訊端函數

  socket、WSASocket,建立完通訊端後可用下面函數控制通訊端的選項和通訊端

  行為:setsockopt、getsockopt、ioctlsocket、WSAIoctl

下面是TCP伺服器端程式樣本

// 模組名:tcpserver.cpp//// 描  述:此例子示範了如何開發一個簡單的TCP伺服器應用程式,//         此應用程式在5150連接埠上監聽TCP串連並接收資料。此//         例子以控制台的形式實現,當接受串連或接收到資料時//         只是簡單的在控制台上列印出資訊。//// 編  譯:注意要設定ws2_32.lib庫,工程-->設定-->串連,將//         ws2_32.lib添加到“對象/庫模組”的最後。#include <winsock2.h>#include <stdio.h>void main(void){// 初始化Winsock,使用2.2版本int     Ret;WSADATA wsaData;if ((Ret = WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)){// 注意:WSAStartup載入失敗,我們不能像平常那樣使用WSAGetLastError//       來得到錯誤碼,但可以根據返回狀態來判斷printf("WSAStartup失敗,錯誤碼 %d\n", Ret);return;}// 建立socketSOCKET ListeningSocket;if ((ListeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET){printf("建立socket失敗,錯誤碼 %d\n", WSAGetLastError());WSACleanup();return;}// 設定SOCKADDR_IN結構體,注意要將連接埠號碼轉換為網路位元組序 SOCKADDR_IN ServerAddr;int         Port = 5150;ServerAddr.sin_family = AF_INET;ServerAddr.sin_port = htons(Port);ServerAddr.sin_addr.s_addr = htonl(INADDR_ANY);// 將地址資訊與socket綁定if (bind(ListeningSocket, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR){printf("綁定失敗,錯誤碼 %d\n", WSAGetLastError());closesocket(ListeningSocket);WSACleanup();return;}// 監聽用戶端串連,排隊隊列長度為5if (listen(ListeningSocket, 5) == SOCKET_ERROR){printf("監聽失敗,錯誤碼 %d\n", WSAGetLastError());closesocket(ListeningSocket);WSACleanup();return;}printf("正在連接埠 %d 上等待串連。\n", Port);SOCKADDR_IN ClientAddr;int         ClientAddrLen = sizeof(ClientAddr);SOCKET      NewConnection;if ((NewConnection = accept(ListeningSocket, (SOCKADDR*)&ClientAddr, &ClientAddrLen)) == INVALID_SOCKET){printf("接受串連失敗,錯誤碼 %d\n", WSAGetLastError());closesocket(ListeningSocket);WSACleanup();return;}printf("從 %s:%d 接收到一個串連。\n", inet_ntoa(ClientAddr.sin_addr), ntohs(ClientAddr.sin_port));// 到此為止,有兩種選擇:一個是使用ListeningSocket繼續accept用戶端串連並// 收發資料。另一種是關閉ListeningSocket不再接收用戶端串連。在這我們選擇// 不再接收用戶端串連,僅是簡單的與剛建立的串連NewConnection進行收發資料closesocket(ListeningSocket);// 使用NewConnection進行收發資料,簡單起見我們只是收一些資料並報告接收到的長度char DataBuffer[1024];printf("正在等待接收資料...\n");if ((Ret = recv(NewConnection, DataBuffer, sizeof(DataBuffer), 0)) == SOCKET_ERROR){printf("接收資料失敗,錯誤碼 %d\n", WSAGetLastError());closesocket(NewConnection);WSACleanup();return;}printf("成功接收 %d 位元組資料\n", Ret);// 不再做任何事情,所以關閉用戶端串連printf("關閉用戶端串連\n");closesocket(NewConnection);// 程式處理完串連後調用WSACleanupWSACleanup();}

下面是TCP用戶端程式樣本

// 模組名:tcpclient.cpp//// 描  述:此例子示範了如何開發一個簡單的TCP用戶端應用程式,//         此程式只是簡單的往伺服器監聽的5150連接埠上發送一個//         "hello"資訊。此例子以控制台的形式實現,當串連成功//         或將資料發送到伺服器時只是簡單的在控制台上列印出資訊。//         // 編  譯:注意要設定ws2_32.lib庫,工程-->設定-->串連,將//         ws2_32.lib添加到“對象/庫模組”的最後。#include <winsock2.h>#include <stdio.h>void main(int argc, char** argv){// 必須為IP作為命令列參數if (argc <= 1){printf("用法:tcpclient <伺服器IP>。\n");return;}// 初始化Winsock,使用2.2版本int     Ret;WSADATA wsaData;if ((Ret = WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)){// 注意:WSAStartup載入失敗,我們不能像平常那樣使用WSAGetLastError//       來得到錯誤碼,但可以根據返回狀態來判斷printf("WSAStartup失敗,錯誤碼 %d\n", Ret);return;}// 建立socketSOCKET s;if ((s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == INVALID_SOCKET){printf("建立socket失敗,錯誤碼 %d\n", WSAGetLastError());WSACleanup();return;}// 設定SOCKADDR_IN結構體,注意要將連接埠號碼轉換為網路位元組序 SOCKADDR_IN ServerAddr;int         Port = 5150;ServerAddr.sin_family = AF_INET;ServerAddr.sin_port = htons(Port);ServerAddr.sin_addr.s_addr = inet_addr(argv[1]);printf("正在串連 %s:%d ...\n", inet_ntoa(ServerAddr.sin_addr), ntohs(ServerAddr.sin_port));if (connect(s, (SOCKADDR*)&ServerAddr, sizeof(ServerAddr)) == SOCKET_ERROR){printf("無法串連,錯誤碼 %d\n", WSAGetLastError());closesocket(s);WSACleanup();return;}printf("串連成功。\n");printf("嘗試發送“hello”資訊\n");if ((Ret = send(s, "Hello", 5, 0)) == SOCKET_ERROR){printf("發送失敗,錯誤碼 %d\n", WSAGetLastError());closesocket(s);WSACleanup();return;}printf("成功發送 %d 位元組資料\n", Ret);// 不再做任何事情,所以關閉用戶端串連printf("關閉串連\n");closesocket(s);// 程式處理完串連後調用WSACleanupWSACleanup();}

UDP接收端樣本

// 模組名:udpreceiver.cpp//// 描  述:此例子示範了如何開發一個簡單的UDP接收程式,//         它在5150連接埠上等待資料包。例子以控制台的//         形式實現,當接收到資料時只是簡單的在控制//         台上列印出資訊。//// 編  譯:注意要設定ws2_32.lib庫,工程-->設定-->串連,將//         ws2_32.lib添加到“對象/庫模組”的最後。#include <winsock2.h>#include <stdio.h>void main(int argc, char** argv){// 初始化Winsock,使用2.2版本int     Ret;WSADATA wsaData;if ((Ret = WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)){// 注意:WSAStartup載入失敗,我們不能像平常那樣使用WSAGetLastError//       來得到錯誤碼,但可以根據返回狀態來判斷printf("WSAStartup失敗,錯誤碼 %d\n", Ret);return;}// 建立socketSOCKET ReceivingSocket;if ((ReceivingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET){printf("建立socket失敗,錯誤碼 %d\n", WSAGetLastError());WSACleanup();return;}// 設定SOCKADDR_IN結構體SOCKADDR_IN ReceiverAddr;int         Port = 5150;ReceiverAddr.sin_family = AF_INET;ReceiverAddr.sin_port = htons(Port);ReceiverAddr.sin_addr.s_addr = htonl(INADDR_ANY);// 將地址資訊與socket綁定if (bind(ReceivingSocket, (SOCKADDR*)&ReceiverAddr, sizeof(ReceiverAddr)) == SOCKET_ERROR){printf("綁定失敗,錯誤碼 %d\n", WSAGetLastError());closesocket(ReceivingSocket);WSACleanup();return;}printf("正在連接埠 %d 上等待接收資料包。\n", Port);char        ReceiveBuf[1024];int         BufLength = 1024;SOCKADDR_IN SenderAddr;int         SenderAddrSize = sizeof(SenderAddr);if ((Ret = recvfrom(ReceivingSocket, ReceiveBuf, BufLength, 0,(SOCKADDR*)&SenderAddr, &SenderAddrSize)) == INVALID_SOCKET){printf("recvfrom失敗,錯誤碼 %d\n", WSAGetLastError());closesocket(ReceivingSocket);WSACleanup();return;}printf("從 %s:%d 接收 %d 位元組資料\n", inet_ntoa(SenderAddr.sin_addr), ntohs(SenderAddr.sin_port), Ret);closesocket(ReceivingSocket);// 程式處理完串連後調用WSACleanupWSACleanup();}

UDP發送端樣本

// 模組名:udpsender.cpp//// 描  述:此例子示範了如何開發一個簡單的UDP發送程式,//         它會向接收端5150連接埠上發送一個"hello"訊息。//         例子以控制台的形式實現,當資訊發送到伺服器時//         只是簡單的在控制台上列印出資訊。//// 編  譯:注意要設定ws2_32.lib庫,工程-->設定-->串連,將//         ws2_32.lib添加到“對象/庫模組”的最後。#include <winsock2.h>#include <stdio.h>void main(int argc, char** argv){// 必須為IP作為命令列參數if (argc <= 1){printf("用法:udpsender <接收端IP>。\n");return;}// 初始化Winsock,使用2.2版本int     Ret;WSADATA wsaData;if ((Ret = WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)){// 注意:WSAStartup載入失敗,我們不能像平常那樣使用WSAGetLastError//       來得到錯誤碼,但可以根據返回狀態來判斷printf("WSAStartup失敗,錯誤碼 %d\n", Ret);return;}// 建立socketSOCKET SendingSocket;if ((SendingSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP)) == INVALID_SOCKET){printf("建立socket失敗,錯誤碼 %d\n", WSAGetLastError());WSACleanup();return;}// 設定SOCKADDR_IN結構體SOCKADDR_IN ReceiverAddr;int         Port = 5150;ReceiverAddr.sin_family = AF_INET;ReceiverAddr.sin_port = htons(Port);ReceiverAddr.sin_addr.s_addr = inet_addr(argv[1]);// 給接收端發送資料包if ((Ret = sendto(SendingSocket, "Hello", 5, 0, (SOCKADDR*)&ReceiverAddr, sizeof(ReceiverAddr))) == SOCKET_ERROR){printf("發送失敗,錯誤碼 %d\n", WSAGetLastError());closesocket(SendingSocket);WSACleanup();return;}printf("成功向 %s:%d 發送 %d 位元組資料\n", inet_ntoa(ReceiverAddr.sin_addr), ntohs(ReceiverAddr.sin_port), Ret);// 發送完資料,關閉串連closesocket(SendingSocket);// 程式處理完串連後調用WSACleanupWSACleanup();}

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.