明輝手游網(wǎng)中心:是一個免費(fèi)提供流行視頻軟件教程、在線學(xué)習(xí)分享的學(xué)習(xí)平臺!

網(wǎng)絡(luò)與黑客編程基本知識

[摘要]第一節(jié) 了解Windows機(jī)制 Windows 是一個“基于事件的, 消息驅(qū)動的”操作系統(tǒng)。   在Windows下執(zhí)行一個程序, 只要用戶進(jìn)...

  第一節(jié) 了解Windows機(jī)制

      Windows 是一個“基于事件的, 消息驅(qū)動的”操作系統(tǒng)。

  在Windows下執(zhí)行一個程序, 只要用戶進(jìn)行了影響窗口的動作(如改變窗口大小或移動、單擊鼠標(biāo)等)該動作就會觸發(fā)一個相應(yīng)的“事件”

系統(tǒng)每次檢測到一個事件時, 就會給程序發(fā)送一個“消息”, 從而使程序可以處理該事件。

  每個Windows 應(yīng)用程序都是基于事件和消息的, 而且包含一個主事件循環(huán), 它不停地、反復(fù)地檢測是否有用戶事件發(fā)生。 每次檢測到一個

用戶事件, 程序就對該事件做出響應(yīng), 處理完再等待下一個事件的發(fā)生。

  Windows 下的應(yīng)用程序不斷地重復(fù)這一過程, 直至用戶終止程序, 用代碼來描述實際上也就是一個消息處理過程的while循環(huán)語句。

  下面便簡單介紹一下與 Windows 系統(tǒng)密切相關(guān)的幾個基本概念:

  1:窗口:這是我要說的第一個概念。 窗口是Windows本身以及Windows 環(huán)境下的應(yīng)用程序的基本界面單位, 但是很多人都誤以為只有具有

標(biāo)題欄、狀態(tài)欄、最大化、最小化按鈕這樣標(biāo)準(zhǔn)的方框才叫窗口。 其實窗口的概念很廣, 例如按鈕和對話框等也是窗口, 只不過是一種特殊化

窗口罷了。

  從用戶的角度看, 窗口就是顯示在屏幕上的一個矩形區(qū)域, 其外觀獨(dú)立于應(yīng)用程序, 事實上它就是生成該窗口的應(yīng)用程序與用戶間的直觀

接口;從應(yīng)用程序的角度看, 窗口是受其控制的一部分矩形屏幕區(qū)。 應(yīng)用程序生成并控制與窗口有關(guān)的一切內(nèi)容, 包括窗口的大小、風(fēng)格、位

置以及窗口內(nèi)顯示的內(nèi)容等。 用戶打開一個應(yīng)用程序后, 程序?qū)?chuàng)建一個窗口, 并在那里默默地等待用戶的要求。 每當(dāng)用戶選擇窗口中的選

項, 程序即對此做出響應(yīng)。

  2:程序:通常說的程序都是指一個能讓計算機(jī)識別的文件, 接觸得最多的便是.exe型的可執(zhí)行文件.

  3:進(jìn)程:說到進(jìn)程, 學(xué)過《操作系統(tǒng)》的人都很清楚, 所謂進(jìn)程就是應(yīng)用程序的執(zhí)行實例(或稱一個執(zhí)行程序) 需要注意的是:進(jìn)程是

程序動態(tài)的描述, 而上面說到的程序是靜態(tài)的描述, 兩者有本質(zhì)的區(qū)別。 舉個例子, 從網(wǎng)上 Down了一個瑞星殺毒軟件到C盤但沒有運(yùn)行, 那

個.exe 可執(zhí)行文件叫做程序, 它是一個二進(jìn)制碼的文件。 一旦雙擊了exe文件圖標(biāo)運(yùn)行程序, 那個“正在運(yùn)行著的瑞星殺毒”便稱為進(jìn)程, 它

在雙擊的那一刻被系統(tǒng)創(chuàng)建, 當(dāng)你關(guān)機(jī)或者在任務(wù)欄的圖標(biāo)上單擊鼠標(biāo)右鍵選“退出”時, 進(jìn)程便消亡, 徹底結(jié)束了生命。 進(jìn)程經(jīng)歷了由“創(chuàng)

建”到“消亡”的生命期, 而程序自始至終存在于你的硬盤上, 不管你的機(jī)器是否啟動。

  4:線程:線程是進(jìn)程中的一個執(zhí)行單元, 同一個進(jìn)程中的各個線程對應(yīng)于一組CPU指令、一組CPU寄存器以及一堆棧。 進(jìn)程本來就具有動態(tài)

的含義, 然而實質(zhì)上是通過線程來執(zhí)行體現(xiàn)的, 從這個意義上說, Windows 中進(jìn)程的動態(tài)性意義已經(jīng)不是很明顯了, 只算是給程序所占的資源

劃定一個范圍而已, 真正具有動態(tài)性意義的是線程。

  5:消息:我們幾乎做每一個動作都會產(chǎn)生一個消息,鼠標(biāo)被移動會產(chǎn)生WM_MOUSEMOVE消息, 鼠標(biāo)左鍵被按下會產(chǎn)生WM_LBUTTONDOWN的消

息, 鼠標(biāo)右鍵按下便產(chǎn)生WM_RBUTTONDOWN消息等等。 所有的這些都可以通過GetMessage, SendMessage等函數(shù)得到.

  6:事件:如在程序運(yùn)行的過程中改變窗口的大小或者移動窗口等, 都會觸發(fā)相應(yīng)的“事件”。

  7:句柄:單單一個“柄”字便可以解釋它的意思了, 我們天氣熱搖扇子的時候只要抓住扇柄便可以控制整個扇子的運(yùn)動了, 在程序中也

差不多是這個意思。 通常一個句柄就可以傳遞我們所要做的事情。 有經(jīng)驗的成員肯定清楚, 編寫程序總是要和各種句柄打交道的, 句柄是

系統(tǒng)用來標(biāo)識不同對象類型的工具, 如窗口、菜單等, 這些東西在系統(tǒng)中被視為不同類型的對象, 用不同的句柄將他們區(qū)分開來。

  C++ 教材中給句柄下的定義是:“在Win32里, 句柄是指向一個無值型對象(void *)的指針, 是一個4字節(jié)長的數(shù)據(jù)”。 從結(jié)構(gòu)

上看, 句柄的確是一個指針, 盡管它沒有指向用于存儲某個對象的內(nèi)存位置, 而實際上句柄指向的是一個包含了對該對象進(jìn)行的引用的位置。

在編程時, 只要抓住了對象的句柄就可以對該對象進(jìn)行操作了.

  

 

  8:API與SDK:API是英文 Application Programming Interface 的簡稱, 意為“應(yīng)用程序接口”, 泛指系統(tǒng)為應(yīng)用程序提供的一系列接

口函數(shù)。 其實質(zhì)是程序內(nèi)的一套函數(shù)調(diào)用, 在編程的時候可以直接調(diào)用, 而不必知道其內(nèi)部實現(xiàn)的過程, 只知道它的原型和返回值就可以

了.

  SDK是英文 Software Development Kit 的縮寫,指“軟件開發(fā)工具包”, 在防火墻的設(shè)計中就經(jīng)常涉及到SDK。

        第二節(jié) Win API編程簡介

  

   下面介紹一下WIN API.

   我們需要自己編寫一個工具時,必然會用到很多操作windows和控制windows的函數(shù),這些函數(shù)就是windows API.

   API是Application Progamming Interface的縮寫.就是說API是一系列已經(jīng)定義的在windows內(nèi)部的函數(shù),是應(yīng)用程序和系統(tǒng)之間的

橋梁,應(yīng)用程序通過調(diào)用API來請求系統(tǒng)完成一系列的任務(wù).窗口,菜單,文件操作等都是通過API實現(xiàn)的.

   WIN32 API就是WINDOWS 32位平臺的應(yīng)用程序接口.現(xiàn)在可視化編程工具提供了大量控件,他們代替了API的功能.這些控件都是構(gòu)建

在WIN32 API之上的.是封裝了的API函數(shù)集合.但是對于比較復(fù)雜和特殊功能(想我們的黑客編程)來說,就必須用API函數(shù)來實現(xiàn).

   WIN API存放在動態(tài)鏈接庫(DLL)中,在98系統(tǒng)中,有32位的GDI32.DLL,KERNEL32.DLL,16位的GDI.EXE,KRNL386.EXE.API就存放在這些

動態(tài)鏈接庫中.

   木馬和后門其實就是使用了文件操作函數(shù),這里做簡要介紹:

        刪除文件:BOOL DeleteFile(LPCTSH lpFileName)

        復(fù)制文件:BOOL CopyFile()

        移動文件:BOOL MoveFile()等等

具體的API可以上網(wǎng)自己去查看,有很多介紹API的書籍.

        第二節(jié) Win API編程簡介

  

   下面介紹一下WIN API.

   我們需要自己編寫一個工具時,必然會用到很多操作windows和控制windows的函數(shù),這些函數(shù)就是windows API.

   API是Application Progamming Interface的縮寫.就是說API是一系列已經(jīng)定義的在windows內(nèi)部的函數(shù),是應(yīng)用程序和系統(tǒng)之間的

橋梁,應(yīng)用程序通過調(diào)用API來請求系統(tǒng)完成一系列的任務(wù).窗口,菜單,文件操作等都是通過API實現(xiàn)的.

   WIN32 API就是WINDOWS 32位平臺的應(yīng)用程序接口.現(xiàn)在可視化編程工具提供了大量控件,他們代替了API的功能.這些控件都是構(gòu)建

在WIN32 API之上的.是封裝了的API函數(shù)集合.但是對于比較復(fù)雜和特殊功能(想我們的黑客編程)來說,就必須用API函數(shù)來實現(xiàn).

   WIN API存放在動態(tài)鏈接庫(DLL)中,在98系統(tǒng)中,有32位的GDI32.DLL,KERNEL32.DLL,16位的GDI.EXE,KRNL386.EXE.API就存放在這些

動態(tài)鏈接庫中.

   木馬和后門其實就是使用了文件操作函數(shù),這里做簡要介紹:

        刪除文件:BOOL DeleteFile(LPCTSH lpFileName)

        復(fù)制文件:BOOL CopyFile()

        移動文件:BOOL MoveFile()等等

具體的API可以上網(wǎng)自己去查看,有很多介紹API的書籍.

          第二節(jié) Win API編程簡介

  

   下面介紹一下WIN API.

   我們需要自己編寫一個工具時,必然會用到很多操作windows和控制windows的函數(shù),這些函數(shù)就是windows API.

   API是Application Progamming Interface的縮寫.就是說API是一系列已經(jīng)定義的在windows內(nèi)部的函數(shù),是應(yīng)用程序和系統(tǒng)之間的

橋梁,應(yīng)用程序通過調(diào)用API來請求系統(tǒng)完成一系列的任務(wù).窗口,菜單,文件操作等都是通過API實現(xiàn)的.

   WIN32 API就是WINDOWS 32位平臺的應(yīng)用程序接口.現(xiàn)在可視化編程工具提供了大量控件,他們代替了API的功能.這些控件都是構(gòu)建

在WIN32 API之上的.是封裝了的API函數(shù)集合.但是對于比較復(fù)雜和特殊功能(想我們的黑客編程)來說,就必須用API函數(shù)來實現(xiàn).

   WIN API存放在動態(tài)鏈接庫(DLL)中,在98系統(tǒng)中,有32位的GDI32.DLL,KERNEL32.DLL,16位的GDI.EXE,KRNL386.EXE.API就存放在這些

動態(tài)鏈接庫中.

   木馬和后門其實就是使用了文件操作函數(shù),這里做簡要介紹:

        刪除文件:BOOL DeleteFile(LPCTSH lpFileName)

        復(fù)制文件:BOOL CopyFile()

        移動文件:BOOL MoveFile()等等

具體的API可以上網(wǎng)自己去查看,有很多介紹API的書籍.

第三節(jié) Windows 網(wǎng)絡(luò)協(xié)議

    

    首先介紹一下網(wǎng)絡(luò)協(xié)議:網(wǎng)絡(luò)協(xié)議是網(wǎng)絡(luò)上所有設(shè)備之間通信規(guī)則的集合,他定義了通信時信息必須采用的格式和這些格式的意義.大多數(shù)

網(wǎng)絡(luò)協(xié)議都采用分層體系結(jié),每一層都建立在他的下層之上,向他的上一層提供服務(wù),而把如何實現(xiàn)這一服務(wù)的細(xì)節(jié)對上層加以屏蔽.一臺設(shè)備上

的第N層與另一臺設(shè)備上的第N層進(jìn)行通信的規(guī)則就是第N曾協(xié)議.在網(wǎng)絡(luò)上的個層之間中存在著許多協(xié)議,接受方和發(fā)送方同層的協(xié)議必須一致,

否則,一方就無法識別另一方發(fā)出的信息.網(wǎng)絡(luò)協(xié)議使網(wǎng)絡(luò)上的設(shè)備各種設(shè)備能相互交換信息.

    常用的協(xié)議有:TCP/IP協(xié)議,IPX/SPX歇息等等.在局域網(wǎng)中常用的IPX/SPX協(xié)議.而訪問INTERNET,就必須添加TCP/IP協(xié)議.

  

    TCP/IP協(xié)議是傳輸控制協(xié)議/互聯(lián)網(wǎng)絡(luò)協(xié)議.他規(guī)范了網(wǎng)絡(luò)上所有設(shè)備的通信,尤其是一個主機(jī)與另一個主機(jī)之間的數(shù)據(jù)往來格式以及傳送

方式.

    在網(wǎng)絡(luò)的各層中還存在著許多協(xié)議,下面列出部分網(wǎng)絡(luò)協(xié)議規(guī)范:

   arp  地址解析協(xié)議

   SNMP 網(wǎng)絡(luò)管理協(xié)議

   BOOTP  讓無盤站從一個中心服務(wù)器上獲得IP地址

   DHCP 動態(tài)主機(jī)配置協(xié)議

   下面介紹網(wǎng)絡(luò)7層協(xié)議在WINDOWS的實現(xiàn):

  

    7層協(xié)議         WIN系統(tǒng)    

________________________________________

   7  應(yīng)用層       7  應(yīng)用程序

________________________________________________

   6  表示層       6  WINSOCK API(DLL)

___________________________________________

   5  會話層       5  SPI(DLL)

__________________________________________________

   4  傳輸層       4  TDI(VXD,SYS)

___________________________________________________

   3  網(wǎng)絡(luò)層       3  NDIS(VXD,SYS)

__________________________________________________

   2  數(shù)據(jù)鏈路層   2  網(wǎng)卡驅(qū)動程序(VXD,SYS)

___________________________________________

   1  物理層       1  網(wǎng)卡

_________________________________________________

相信這個映射圖可以讓大家比較清楚了解他們的對應(yīng)關(guān)系

     TCP協(xié)議圖示

應(yīng)用程序協(xié)議     HTTP FTP  TELNET

傳輸協(xié)議         TCP UDP

網(wǎng)際協(xié)議         IP

物理層協(xié)議       網(wǎng)卡

    IP協(xié)議保證數(shù)據(jù)的傳輸,TCP協(xié)議保證數(shù)據(jù)傳輸?shù)馁|(zhì)量.

    TCP/IP協(xié)議基于四層結(jié)構(gòu):應(yīng)用層,傳輸層,網(wǎng)絡(luò)層,接口層,數(shù)據(jù)在傳輸時每通過一層就要在數(shù)據(jù)上加個頭,其中的數(shù)據(jù)供接受端同層使用,在

接收端,每經(jīng)過一層就把頭去掉,來保證傳輸數(shù)據(jù)格式的一致.

TCP頭部結(jié)構(gòu):

                          16位源端口號        16位目的端口號

_______________________________________________________________________________

                                   32位序列號

___________________________________________________________________________

                                   32位確認(rèn)號

_____________________________________________________________________________________

                 4位首部長度+6位保留字 6位標(biāo)志  16位窗口大小

_______________________________________________________________________________________

                          16位效驗和             16位緊急數(shù)據(jù)偏移量

_____________________________________________________________________________________

                                     數(shù)據(jù)段

_______________________________________________________________________________

IP頭部結(jié)構(gòu):

                       4位IP版本號  4位首部長度  8位服務(wù)類型  16位總長度

___________________________________________________________________________________________

                                    16位標(biāo)示                   3位標(biāo)志和偏移

                      __________________________________________________________________________

                       8位生存時間    8位協(xié)議                  16位IP首部效驗和

_________________________________________________________________________________________

                                 32位源IP地址

___________________________________________________________________________________________

                              32位目的IP地址      

________________________________________________________________________________________

                              TCP頭和數(shù)據(jù)

____________________________________________________________________________

第四節(jié) 關(guān)于服務(wù)器和客戶端編程

       在網(wǎng)絡(luò)編程中,最常用和最基礎(chǔ)的就是WINSOCK. 現(xiàn)在我們討論WINDOWS下的SOCKET編程.

    

       大凡在WIN32平臺上的WINSOCK編程都要經(jīng)過下列步驟:

     定義變量->獲得WINDOCK版本->加載WINSOCK庫->初始化->創(chuàng)建套接字->設(shè)置套接字選項->關(guān)閉套接字>卸載WINSOCK庫->釋放資源

    下面介紹WINSOCK C/S的建立過程:

    服務(wù)器                        客戶端

________________________________________________

1  初始化WSA                     1  初始化WSA

____________________________________________________

2  建立一個SOCKET                2  建立一個SOCKET

_____________________________________________________

3  綁定SOCKET                    3  連接到服務(wù)器

_____________________________________________________

4  在指定的端口監(jiān)聽              4  發(fā)送和接受數(shù)據(jù)

_____________________________________________________

5  接受一個連接                  5   斷開連接

______________________________________________________-

6  發(fā)送和接受數(shù)據(jù)

___________________________________________________

7  斷開連接

__________________________________________________

  

   大家注意,在VC中進(jìn)行WINSOCK編程時,需要引入如下兩個庫文件:WINSOCK.H(這個是WINSOCK API的頭文件,WIN2K以上支持WINSOCK2,所以

可以用WINSOCK2.H);Ws2_32.lib(WINSOCK API連接庫文件).

使用方式如下:

              #include <winsock.h>

              #pragma comment(lib,"ws2_32.lib")

  

  下面我們通過具體的代碼演示服務(wù)器和客戶端的工作流程:

首先,建立一個WSADATA結(jié)構(gòu),通常用wsaData

WSADATA wsaData;

然后,調(diào)用WSAStartup函數(shù),這個函數(shù)是連接應(yīng)用程序與winsock.dll的第一個調(diào)用.其中,第一個參數(shù)是WINSOCK 版本號,第二個參數(shù)是指向

WSADATA的指針.該函數(shù)返回一個INT型值,通過檢查這個值來確定初始化是否成功.調(diào)用格式如下:WSAStartup(MAKEWORD(2,2),&wsaData),其中

MAKEWORD(2,2)表示使用WINSOCK2版本.wsaData用來存儲系統(tǒng)傳回的關(guān)于WINSOCK的資料.

if(iResuit=WSAStartup(MAKEWORD(2,2),&wsaData)!=0)

{

        printf("WSAStartup failed:%d",GetLastError());  //返回值不等與0,說明初始化失敗

        ExitProcess();                                  //退出程序

}

應(yīng)用程序在完成對請求的SOCKET庫使用后,要調(diào)用WSACleanup函數(shù)來接觸SOCKET庫的綁定,并且釋放資源.

注意WSAStartup初始化后,必須建立一個SOCKET結(jié)構(gòu)來保存SOCKET句柄.

下面我們建立一個SOCKET.

首先我們建立一個m_socket的SOCKET句柄,接著調(diào)用socket()函數(shù),函數(shù)返回值保存在m_socket中.我們使用AF_INFE,SOCK_STREAM,IPPROTO_TCP

三個參數(shù).第一個表示地址族,AF_INFE表示TCP/IP族,第二個表示服務(wù)類型,在WINSOCK2中,SOCKET支持以下三種類型;

SOCK_STREAM 流式套接字

SOCK_DGRAM  數(shù)據(jù)報套接字

SOCK_RAW    原始套接字

第三個參數(shù)表示協(xié)議:

IPPROTO_UDP  UDP協(xié)議 用于無連接數(shù)據(jù)報套接字

IPPROTO_TCP  TCP協(xié)議 用于流式套接字

IPPROTO_ICMP ICMP協(xié)議用于原始套接字

m_socket=socket(AF_INFE,SOCK_STREAM,IPPROTO_TCP);    //創(chuàng)建TCP協(xié)議

以下代碼用于檢查返回值是否有錯誤:

if(m_scoket==INVALID_SOCKET)

{

        prinrf("Error at socket():%d\n",GetLastError());

        WSACleanup();                                   //釋放資源

        return;                                  

}

說明,如果socket()調(diào)用失敗,他將返回INVALID_SOCKET.

    為了服務(wù)器能接受一個連接,他必須綁定一個網(wǎng)絡(luò)地址,下面的代碼展示如何綁定一個已經(jīng)初始化的IP和端口的Socket.客戶端程序用這個

IP地址和端口來連接服務(wù)器.

sockaddr_in service;

service.sin_family=AF_INET;                       //INTERNET地址族

service.sin_addr.s_addr=inet_addr("127.0.0.1");   //將要綁定的本地IP地址

service.sin_port=htons(27015);                     //27015將要綁定的端口

下面我們調(diào)用BIND函數(shù),把SOCKET和SOCKADDR以參數(shù)的形式傳入,并檢查錯誤.

if(bind(m_socket,(SOCKADDR*)&SERVICE,sizeof(service))==SOCKET_ERROR)

{

        printf("bind() failed.\n");

        closesocket(m_socket);

        return;

}

   當(dāng)綁定完成后,服務(wù)器必須建立一個監(jiān)聽隊列,以接受客戶端的請求.listen()使服務(wù)器進(jìn)入監(jiān)聽狀態(tài),該函數(shù)調(diào)用成功返回0,否則返回

SOCKET_ERROR.代碼如下:

if(listen(m_socket,1)==SOCKET-ERROR)

{

        printf("error listening on socket.\n");

}

服務(wù)器端調(diào)用完LISTEN()后,如果此時客戶端調(diào)用CONNECT()函數(shù),服務(wù)器端必須在調(diào)用ACCEPT().這樣服務(wù)器和客戶端才算正式完成通信程序的

連接動作.

一旦服務(wù)器開始監(jiān)聽,我們就要指定一個句柄來表示利用ACCEPT()函數(shù)接受的連接,這個句柄是用來發(fā)送和接受數(shù)據(jù)的表示.建立一個SOCKET句柄

Socket AcceptSocket 然后利用無限循環(huán)來檢測是否有連接傳入.一但有連接請求,ACCEPT()函數(shù)就會被調(diào)用,并且返回這次連接的句柄.

printf("waitong for a client to connect...\n");

while(1)

{

        AcceptSocket=SOCKET_ERROR;

        while(AcceptSocket==SOCKET_ERROR)

        {

                AcceptSocket=accept(m_socket,NULL,NULL);

        }

}

下面看客戶端端代碼:

        

sockaddr_in clientService;

clientService.sin_family=AF_INET;                       //INTERNET地址族

clientService.sin_addr.s_addr=inet_addr("127.0.0.1");   //將要綁定的本地IP地址

clientService.sin_port=htons(27015);                     //27015將要綁定的端口

下面調(diào)用CONNECT()函數(shù):

if ( connect( m_socket, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR)

{

        printf( "Failed to connect.\n" );

        WSACleanup();

        return;

}                                                                     //如果調(diào)用失敗清理退出

                                                                      //調(diào)用成功繼續(xù)讀寫數(shù)據(jù)

_____________________________________________________________________________________

到這里,服務(wù)器和客戶端的基本流程介紹完畢,下面我們介紹數(shù)據(jù)交換.

send():

int send

{

        SOCKET s,                    //指定發(fā)送端套接字

        const char FAR?*buf,         //指明一個存放應(yīng)用程序要發(fā)送的數(shù)據(jù)的緩沖區(qū)

        int len,                     //實際要發(fā)送的數(shù)據(jù)字節(jié)數(shù)

        int flags                    //一般設(shè)置為0

};

C/S都用SEND函數(shù)向TCP連接的另一端發(fā)送數(shù)據(jù).

recv():

int recv

{

        SOCKET s,                    //指定發(fā)送端套接字

        char FAR?*buf,              //指明一個緩沖區(qū) 存放RECC受到的數(shù)據(jù)

        int len,                     //指明BUF的長度

        int flags                    //一般設(shè)置為0

};

C/S都使用RECV函數(shù)從TCP連接的另一端接受數(shù)據(jù)

_______________________________________________________________________________________________

下面將完整的程序代碼提供如下,大家可直接編譯運(yùn)行

首先看客戶端的代碼:

#include <stdio.h>

#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")

void main() {

                                                                         // 初始化 Winsock.

    WSADATA wsaData;

    int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );

    if ( iResult != NO_ERROR )

        printf("Error at WSAStartup()\n");

                                                                            // 建立socket socket.

    SOCKET client;

    client = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

    if ( client == INVALID_SOCKET ) {

        printf( "Error at socket(): %ld\n", WSAGetLastError() );

        WSACleanup();

        return;

    }

                                                                             // 連接到服務(wù)器.

    sockaddr_in clientService;

    clientService.sin_family = AF_INET;

    clientService.sin_addr.s_addr = inet_addr( "127.0.0.1" );

    clientService.sin_port = htons( 27015 );

    if ( connect( client, (SOCKADDR*) &clientService, sizeof(clientService) ) == SOCKET_ERROR) {

        printf( "Failed to connect.\n" );

        WSACleanup();

        return;

    }

                                                                                 // 發(fā)送并接收數(shù)據(jù).

    int bytesSent;

    int bytesRecv = SOCKET_ERROR;

    char sendbuf[32] = "Client: Sending data.";

    char recvbuf[32] = "";

    bytesSent = send( client, sendbuf, strlen(sendbuf), 0 );

    printf( "Bytes Sent: %ld\n", bytesSent );

    while( bytesRecv == SOCKET_ERROR ) {

        bytesRecv = recv( client, recvbuf, 32, 0 );

        if ( bytesRecv == 0 bytesRecv == WSAECONNRESET ) {

            printf( "Connection Closed.\n");

            break;

        }

        if (bytesRecv < 0)

            return;

        printf( "Bytes Recv: %ld\n", bytesRecv );

    }

    return;

}

下面是服務(wù)器端代碼:

#include <stdio.h>

#include <winsock2.h>

#pragma comment(lib, "ws2_32.lib")

void main() {

                                                                              // 初始化

    WSADATA wsaData;

    int iResult = WSAStartup( MAKEWORD(2,2), &wsaData );

    if ( iResult != NO_ERROR )

        printf("Error at WSAStartup()\n");

                                                                                // 建立socket

    SOCKET server;

    server = socket( AF_INET, SOCK_STREAM, IPPROTO_TCP );

    if ( server == INVALID_SOCKET ) {

        printf( "Error at socket(): %ld\n", WSAGetLastError() );

        WSACleanup();

        return;

    }

                                                                                         // 綁定socket

    sockaddr_in service;

    service.sin_family = AF_INET;

    service.sin_addr.s_addr = inet_addr( "127.0.0.1" );

    service.sin_port = htons( 27015 );

    if ( bind( server, (SOCKADDR*) &service, sizeof(service) ) == SOCKET_ERROR ) {

        printf( "bind() failed.\n" );

        closesocket(server);

        return;

    }

    

                                                                              // 監(jiān)聽 socket

    if ( listen( server, 1 ) == SOCKET_ERROR )

        printf( "Error listening on socket.\n");

                                                                                // 接受連接

    SOCKET AcceptSocket;

    printf( "Waiting for a client to connect...\n" );

    while (1) {

        AcceptSocket = SOCKET_ERROR;

        while ( AcceptSocket == SOCKET_ERROR ) {

            AcceptSocket = accept( server, NULL, NULL );

        }

        printf( "Client Connected.\n");

        server = AcceptSocket;

        break;

    }

    

                                                                                     // 發(fā)送接受數(shù)據(jù)

    int bytesSent;

    int bytesRecv = SOCKET_ERROR;

    char sendbuf[32] = "Server: Sending Data.";

    char recvbuf[32] = "";

    

    bytesRecv = recv( server, recvbuf, 32, 0 );

    printf( "Bytes Recv: %ld\n", bytesRecv );

    

    bytesSent = send( server, sendbuf, strlen(sendbuf), 0 );

    printf( "Bytes Sent: %ld\n", bytesSent );

    return;

}

本程序僅僅描述了同步的情況!

   第五節(jié) 多線程編程介紹

    對于多線程的基本概念,我不在贅述,是個只要學(xué)習(xí)過一門編程語言就應(yīng)該多進(jìn)程和線程有個基本的了解.這里重點介紹一下如何實現(xiàn)多線程.

通常一個程序的主線程有操作系統(tǒng)創(chuàng)建,如果想讓其創(chuàng)建額外的線程,可以調(diào)用CreateThread()函數(shù)來完成.函數(shù)原形如下:

HANDLE CreateThread()

{

        LPSECURITY_ATTRIBUTES LPThreadAttributes,  //指向SECURITY_ATTRIBUTES的指針

        SIZE_T dwStackSize,                        //表示線程為自己所用堆棧分配的地址空間的大小 系統(tǒng)缺省值為0

        LPTHREAD_START-TOUTINE lpStartAddress,     //表示新線程開始執(zhí)行時代碼所在函數(shù)的地址 即線程函數(shù)名

        LPVOID lpParameter,                        //是傳入線程函數(shù)的參數(shù)

        DWORD dwCreationFlags,                     //指定控制線程創(chuàng)建的附加標(biāo)志 取0線程立即執(zhí)行 取CREATE_SUSPENDED線程掛起

        LPDWORD lpThreadld                         //是個DWORD類型的地址,返回賦給該新線程的ID

}

線程函數(shù)lpParameter必須有以下原形:

DWORD WINAPI XXXThreadFun(LPVOID lpParameter)

{

        return(0);

}

________________________________________________________________________________________

下面我們來創(chuàng)建一個線程:

#include <windows.h>

#include <stdio.h>

DWORD WINAPI ThreadFunc( LPVOID lpParam )                         //線程函數(shù), 跟普通的函數(shù)沒什么兩樣

{

    printf( "Parameter = %d.", *(DWORD*)lpParam );

return 0;

}

VOID main( VOID )

{

    DWORD dwThreadId, dwThrdParam = 1;

    HANDLE hThread;

hThread = CreateThread( NULL,0,ThreadFunc,&dwThrdParam, 0,&dwThreadId);

      if (hThread == NULL)

   {

      printf( "CreateThread failed (%d)\n", GetLastError() );

   }

   else

   {

      _getch();

      CloseHandle( hThread );

   }

}

關(guān)于線程同步的問題,這里就不再講解,請大家自己查閱資料,不查閱以后可能會有困難啊.培養(yǎng)一下各位的自己動手能力.


上面是電腦上網(wǎng)安全的一些基礎(chǔ)常識,學(xué)習(xí)了安全知識,幾乎可以讓你免費(fèi)電腦中毒的煩擾。