Johnnie Megnyerő bemutatója

Altal Johnnie Rose, Jr.

Ha már szándékosan megérkezett a Megnyerő bemutató, amit valószínűleg az ötletet a saját kommunikáló alkalmazások az interneten keresztül, mint lenyűgöző kilátás, mint én. Vagy talán valaki más találta kilátásba egyaránt érdekes és akkor már megbízott hozza ezt az álom valósággá válik. Mindkét esetben a Winsock hálózati szolgáltatás, és ez a bemutató segít a célok elérésében a kereskedelmi vállalkozás, egyszerűen feltárása birodalmában műsorok személyes használatra, vagy valami a kettő között.

Íme, amit lesz, amely:

Bár lehet, hogy alig várja, hogy elérje ezt a félelmetes pontot, ahol az alkalmazás sikeresen való első kapcsolat, legyen tisztában a fogalmak mögött a kódot. Próbálja meg elkerülni egyszerűen manipulálni a megadott kódot, hogy megfeleljen az Ön igényeinek azonnali és ahelyett azonosítani a követelményeket az alkalmazás, és csak ezután végre, amit úgy tűnik, hogy a legjobb megoldás. Ennyi elég az én Zen Szoftverfejlesztés tanácsot most; keressük meg a hálózati programozás …

Bátran töltse le a teljes útmutatót kód lista. Ne feledje, hogy bármilyen kódot mutatja be ezt a bemutató össze kell kapcsolni a Winsock könyvtár, általában wsock32.lib vagy valami hasonló nevű. Így, amikor kódot pontosan bemutatott a tutorial a saját IDE (Dev-C ++, a Microsoft VC ++, C ++ Builder, stb), úgy dönt, hogy építsenek egy Windows-projekt egy WinMain (), hogy elkerüljék a hibákat.

Létrehozása Socket

Alkalmazások szervizelése kívül gépek hívják kiszolgálók. Szerver alkalmazások hallgatni az ügyfelek által inicializálása egy vagy több hallgat foglalat. Amikor egy ügyfél csatlakozik egy ilyen hallgat aljzatok, a szerver megkapja az értesítést Megnyerő, elfogadja a csatlakozást, és elkezdi a kiszállítást lehallgatott üzeneteket, és az új kliens. Talán a legegyszerűbb módszer, amellyel szerverek több ügyfelet kezelni, hogy kapsz egy új szálat minden kliens kapcsolatot. Ez a szerver modell leggyakrabban használ blokkoló foglalatok, amely rövid időre leállhat várni a beérkező adatokat, egy új kapcsolatot, és egyéb hálózati események. Először is, hadd azonosítani néhány struktúrák akkor kell formáznia a blokkoló socket:

WSADATA: Ez a struktúra lekérdezni az operációs rendszer verziójától Megnyerő kódunk igényel. Az alkalmazás meghívja WSAStartup () elindítani a helyes Megnyerő DLL.
SOCKET: Egy objektum (sőt, ez határozza meg, mint a u_int, előjel nélküli egész, a winsock.h — jó tudni a Smalltalk bulikon) által használt alkalmazások tárolására a socket fogantyú.
SOCKADDR_IN: Egy alkalmazás használja ezt a struktúrát adni, hogy milyen a socket kell működnie. SOCKADDR_IN mezőket tartalmaz egy IP címet és port számot:

struct sockaddr_in

{

  short sin_family;         // Protokoll típusa

  u_short sin_port;         // Port száma aljzat

  struct in_addr sin_addr;  // IP-cím

  char sin_zero[8];         // Felhasználatlan

};

Az első mező a protokoll típusa, amely általában AF_INET (TCP / IP). Ennek Socket nem érintett a hálózati címét a gépet, amelyen lakik, Megnyerő automatikusan kiosztja az IP-címet és port számot hallgatta aljzatok upon létrehozását.

Majd elkészítjük első hallgatás szerver a fenti struktúrák és egy kis sereg a hálózati funkciók:

#include <windows.h>

#include <winsock.h>

#include <stdio.h>



#define NETWORK_ERROR -1

#define NETWORK_OK     0



void ReportError(int, const char *);





int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow)

{

	WORD sockVersion;

	WSADATA wsaData;

	int nret;



	sockVersion = MAKEWORD(1, 1);			// Szeretnénk Megnyerő version 1.1





	// Kezdjük inicializálása Megnyerő

	WSAStartup(sockVersion, &wsaData);





	// Ezután hozzon létre a Socket

	SOCKET listeningSocket;



	listeningSocket = socket(AF_INET,		// Kelj át TCP/IP

			         SOCK_STREAM,   	// Ez egy patak-orientált aljzat

				 IPPROTO_TCP);		// Használja TCP helyett az UDP



	if (listeningSocket == INVALID_SOCKET)

	{

		nret = WSAGetLastError();		// Kap egy részletes hiba

		ReportError(nret, "socket()");		// Jelentés a hiba a mi egyéni funkció



		WSACleanup();				// Shutdown Megnyerő

		return NETWORK_ERROR;			// Hibaüzenetet értéke

	}





	// Használjon SOCKADDR_IN struct kitölteni címadatok

	SOCKADDR_IN serverInfo;



	serverInfo.sin_family = AF_INET;

	serverInfo.sin_addr.s_addr = INADDR_ANY;	// Mivel ez a foglalat figyeli a kapcsolatokat,

							// bármely helyi címet fog tenni

	serverInfo.sin_port = htons(8888);		// Convert egész 8888 hálózati byte sorrendben

							// és helyezze be a port mező





	// Köti a socket, hogy a helyi szerver címét

	nret = bind(listeningSocket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));



	if (nret == SOCKET_ERROR)

	{

		nret = WSAGetLastError();

		ReportError(nret, "bind()");



		WSACleanup();

		return NETWORK_ERROR;

	}





	// Hogy a socket listen

	nret = listen(listeningSocket, 10);		// Akár 10 csatlakozások várni bármikor

							// Egy időben lenni accept()'ed



	if (nret == SOCKET_ERROR)

	{

		nret = WSAGetLastError();

		ReportError(nret, "listen()");



		WSACleanup();

		return NETWORK_ERROR;

	}





	// Várjon egy ügyfél

	SOCKET theClient;



	theClient = accept(listeningSocket,

			   NULL,			// Opcionálisan címét egy SOCKADDR_IN struct

			   NULL);			// Adott esetben változó címét tartalmazó

							// sizeof ( struct SOCKADDR_IN )



	if (theClient == INVALID_SOCKET)

	{

		nret = WSAGetLastError();

		ReportError(nret, "accept()");



		WSACleanup();

		return NETWORK_ERROR;

	}





	// Küldése és fogadása az ügyfél, és végül,

	closesocket(theClient);

	closesocket(listeningSocket);





	// Shutdown Megnyerő

	WSACleanup();

	return NETWORK_OK;

}





void ReportError(int errorCode, const char *whichFunc)

{

   char errorMsg[92];					// Kijelentem, puffer tartani

							// a generált error message

   

   ZeroMemory(errorMsg, 92);				// Automatikusan NULL-terminate the string



   // A következő sort másolja a kifejezést, whichFunc húr, és egész errorCode a puffer

   sprintf(errorMsg, "Call to %s returned error %d!", (char *)whichFunc, errorCode);



   MessageBox(NULL, errorMsg, "socketIndication", MB_OK);

}

Egy dolog, amit azonnal észre a kód a mennyiségű erőfeszítést helyezték hibák ellenőrzése. Amikor hiba lép fel, a kód szerez egy adott hibakód WSAGetLastError (), és az eredményt eltárolja nret. A hibakód ezután elküldésre kerül egy string nevének feltüntetésével a hibás funkciót egy egyedi funkció elemzi ReportError (). Ott, egy hibaüzenet épített és kimutatták, hogy a felhasználó egy hívást, hogy MessageBox (), amely része a standard WinAPI. Például volt hallgatni () nem egy hiba kódja 10093 (definíció szerint WSANOTINITIALISED), a kész hibaszövegeknek lenne “Call hallgatni () hibát jelzett 10093!”. Te, a prudens fejlesztő, akkor nézzetek fel a kódot, és fedezze fel, hogy hiba történt, mert egy sikeres hívás WSAStartup () még nem került sor.

Aleksandar Pavlov bővült ez a ReportError () a leírását tartalmazza, körülbelül egy tucat közös socket hibát. Használja a továbbfejlesztett változata, akkor már nem kell kell keresni, mi a kód jelenti, és a programban lesz sokkal inkább felhasználóbarát, nagyon kevés erőfeszítést az Ön részéről.

Ide tartoznak azok a határozza meg a NETWORK_ERROR és NETWORK_OK. Ezek hasznosak lehetnek, amikor ellenőrzi a visszatérési értéke a saját hálózati funkciókat. Ha a funkciók vissza egy ilyen értékek, a hívó függvény is egy egyszerű egyenlőség vizsgálat tárt fel hibákat: if (myNetworkingFunction () == NETWORK_ERROR) {…}. A hívó függvény is megkaphatja egy adott kódot WSAGetLastError (), és kezelni a hibát kell. Végül, a végrehajtási jó hibaelhárító program most takarít meg több nap vagy hét fejlesztési idő, mint akkor azonnal tudja, hogy miért a programot nem sikerült.

Amellett, hogy visszatérő új ügyfél kapcsolat, fogadja el () segítségével a kiszolgáló kivonat információt az ügyfélről és nem olyan módszerekkel igénylő extra funkciót kéri, vagy időt (ami gondot jelenthetnek játék szerverek, ahol a sebességet a elfogadom loop különösen kritikus). Ahhoz, hogy kihasználják ezt a funkciót, adja át a címe a sockaddr_in struct öntött egy sockaddr mutatót, azaz a (LPSOCKADDR) és aSockaddrInStructure. Továbbá, állapítsa egy egész típusú változó, az értéket a int a sizeof a sockaddr struct, és add meg a címét, az egész, mint a harmadik paraméter. Ha címet információkat kell után visszatért a függvényhívás, a hossza paraméter jelen kell lennie.

jdarnold arra figyelmeztet bennünket, hogy ne higgyenek az MSDN vonatkozó dokumentációkat harmadik paraméter: “Az MSDN docs jelenti, hogy nem kell, hogy adja át a addrlen, hogy ez csak egy választható kimeneti paraméter, de tévednek. bejövő azt mondja, hogy hány bájt a sockaddr puffer, és a kimenő [Megnyerő] kitölti hány [Megnyerő] használni. Ha át nulla, mint a len, [Megnyerő] nem nyúl a puffer. “

Ez nem sok egy szerver, mivel megvárja csak egy felhasználó kapcsolódni, majd azonnal bontja, de ez a legalapvetőbb design. Csak tisztázni a dolgokat, egy hívás, hogy WSAStartup () egy SZÓ meghatározva milyen verziót szeretné betölteni (ebben az esetben ez 1.1) és a címét egy WSADATA szerkezet. Ezután fogjuk fedezni, hogyan lehet csatlakozni más számítógépekhez.

Így a saját Connections

Létrehozása csatlajozó hogy valaki más használta a legtöbb azonos funkciók, kivéve a HOSTENT struct:

Nos, nézzük rögtön a kódot:

#include <windows.h>

#include <winsock.h>

#include <stdio.h>



#define NETWORK_ERROR -1

#define NETWORK_OK     0



void ReportError(int, const char *);





int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow)

{

	WORD sockVersion;

	WSADATA wsaData;

	int nret;



	sockVersion = MAKEWORD(1, 1);





	// Inicializáljon Megnyerő, mint korábban

	WSAStartup(sockVersion, &wsaData);





	// Store információkat a szerver

	LPHOSTENT hostEntry;



	hostEntry = gethostbyname("www.yahoo.com");	// A szerver a neve;

							// Egy másik lehetőség: gethostbyaddr ()



	if (!hostEntry)

	{

		nret = WSAGetLastError();

		ReportError(nret, "gethostbyname()");	// Jelentés a hibát, mint korábban



		WSACleanup();

		return NETWORK_ERROR;

	}





	// Create the socket

	SOCKET theSocket;



	theSocket = socket(AF_INET,			// Kelj át TCP/IP

			   SOCK_STREAM,			// Ez egy patak-orientált aljzat

			   IPPROTO_TCP);		// Használja TCP helyett az UDP



	if (theSocket == INVALID_SOCKET)

	{

		nret = WSAGetLastError();

		ReportError(nret, "socket()");



		WSACleanup();

		return NETWORK_ERROR;

	}





	// Töltsünk meg egy SOCKADDR_IN struct a címadatok

	SOCKADDR_IN serverInfo;



	serverInfo.sin_family = AF_INET;



	// Ezen a ponton, amit sikeresen letöltöttük létfontosságú információkat a szerver,

	// beleértve a hostname, álnevek, és az IP-címeket. Várj; hogyan lehet egyetlen

	// számítógép van több címet, és pontosan mi a következő sort csinál?

	// Lásd az alábbi magyarázat.



	serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);



	serverInfo.sin_port = htons(80);		// Változás, hogy a hálózati bájt sorrend és

							// insert into port mező





	// Kapcsolódni a szerverhez

	nret = connect(theSocket,

		       (LPSOCKADDR)&serverInfo,

		       sizeof(struct sockaddr));



	if (nret == SOCKET_ERROR)

	{

		nret = WSAGetLastError();

		ReportError(nret, "connect()");



		WSACleanup();

		return NETWORK_ERROR;

	}





	// Sikeresen csatlakozott!





	// Küldés/fogadás, majd razzia:

	closesocket(theSocket);

	WSACleanup();

}





void ReportError(int errorCode, const char *whichFunc)

{

   char errorMsg[92];					// Kijelentem, puffer tartani

							// A generált hibaüzenet

   

   ZeroMemory(errorMsg, 92);				// Automatikusan NULL-megszüntetheti a húr



   // A következő sort másolja a kifejezést, whichFunc húr, és egész errorCode a puffer

   sprintf(errorMsg, "Call to %s returned error %d!", (char *)whichFunc, errorCode);



   MessageBox(NULL, errorMsg, "socketIndication", MB_OK);

}

A legbonyolultabb sorban a lista a következő:

serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list);

hajt végre, ezért több műveletet — egyikük viszonylag rejtve — egyszerre. Vessünk szét lépésről lépésre:

A h_addr_list tagja HOSTENT struct alapvetően határozzák meg char ** h_addr_list, ami egy tömböt, vagy char * s. gethostbyname () azonosított és másolt összes ismert címek a szervert a listából. De vajon a koncepció több címet is alapvetően értelme? Tulajdonképpen igen. A számítógép, sőt, van egy sor általános hálózati címeket. Az Ön Internet-cím lehet 205.182.67.96, a LAN-cím lehet 10.0.0.2, és minden számítógépen, amelyen a Windows telepítve természetesen van egy “visszacsatolási” címe 127.0.0.1, a számítógépek által használt utal magát a helyi hálózaton . Ugyanez az elv érvényesül a birodalmában az internetes címek vagy IP-k, ezért a listán van szükség, nem pedig tárhely egyetlen címet. Megjegyzendő, hogy az elsődleges cím, azaz a leginkább elérhető címet, mindig másolja be az első eleme a listán, majd a második preferált vagy egyéb címeket.

Mi * hostEntry-> h_addr_list csinál? Sejteni lehet, hogy a tisztelet operátor (*) van használatban legyen egyetlen címet a listán. Azonban mivel nem egy meghatározott index, a hivatkozás feloldási művelet automatikusan feltárja az első, előnyös címet. Hogy az adott szakasz egyenértékű * hostEntry-> h_addr_list [0], amely garantálja, hogy létezik, mivel a szerver kell legalább egy címet.

Ezután a char * által visszaadott dereferencing működését öntik egy in_addr * vagy LPIN_ADDR. Végül egy másik tisztelettel hajt végre műveletet, hogy visszatérjen a in_addr struct által említett mutatót, ami csak tartani egy címet. A kapott in_addr struct azután rendelt serverInfo.sin_addr. Az ezt követő connect () úgy egy címet kell megadnunk, amikor alkotó kapcsolatot a szerverrel.

Ha a szerver IP cím ismert, egy érvényes HOSTENT lehet beszerezni felhasználása révén gethostbyaddr () (szemben a gethostbyname () használták az előző felsorolás):

LPHOSTENT hostEntry;

in_addr iaHost;



iaHost.s_addr = inet_addr("204.52.135.52");



hostEntry = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr), AF_INET);



if (!hostEntry)

{

	// kezelje megfelelően

}

Ebben az esetben inet_addr () arra használjuk, hogy másolja a string, amely az IP-címet közvetlenül egy in_addr struct. Ezt követően a címét a struct öntünk const char * által előírt gethostbyaddr (). Mindkét módszer nevezik megoldása a szerver címét, mivel Megnyerő visszaadja a teljes címet rekordját részinformációkat.

Néhány további megjegyzés: port 80 használtuk egyszerűen azért, internet weboldal transzfer megtörténik a porton. Ha úgy döntesz, hogy küldjön egy string egy webszerver kérő egy adott fájlt, és megkísérli, hogy valamit kap vissza, ha volna egy nagyon egyszerű böngésző. Persze, hogy karakterlánc az egy teljes HTTP parancsot. Nagyon jó, hogy tudjuk hallgatni, és csatlakozni más számítógépekhez, de a kommunikáció is magában küldésére és fogadására.

Küldése és fogadása

Küldés kezelik, kényelmesen elég, a send () függvényt:

int send(

  SOCKET s,

  const char * FAR buf,

  int len,

  int flags

);

Alapvetően akkor másolja bármit is akart egy tárolóba, és használja a send () függvény egy csatlakoztatott csatlakozó, hogy az adatokat megy a másik végén:

char buffer[256];		// Nyilvánító puffer a stack

char *buffer = new char[256];	// vagy a kupac



ZeroMemory(buffer, 256);

strcpy(buffer, "Pretend this is important data.");



nret = send(theSocket,

	    buffer,

	    strlen(buffer),	// Megjegyzendő, hogy ez határozza meg a hossza a string; nem

				// a méret a teljes puffer

	    0);			// Leggyakrabban nulla, de lásd MSDN más lehetőségeket



delete [] buffer;		// Akkor és csak akkor, ha a kupac nyilatkozatot használták



if (nret == SOCKET_ERROR)

{

	// Kap egy egyedi kódot

	// Kezelje megfelelően

	return NETWORK_ERROR;

} else {

	// nret tartalmazza a küldött bájtok száma

}

Fogadás csak ugyanazt a folyamatot, visszafelé:

char buffer[256];		// A stack

char *buffer = new char[256];	// vagy a kupac



nret = recv(theSocket,

	    buffer,

	    256,		// Teljes méretű puffer

	    0);



delete [] buffer;		// Manipulálni puffert, majd törölje akkor és csak akkor, ha

				// buffer osztották el kupac



if (nret == SOCKET_ERROR)

{

	// Kap egy egyedi kódot

	// kezelje megfelelően

	return NETWORK_ERROR;

} else {

	// nret számát tartalmazza a kapott bájtok

}

Milyen érdekes megjegyezni, hogy van egy gomb az eszköztáron a Microsoft Outlook feliratú “Küldés / Fogadás.” A “vételi” rövidítve “Recv” egyszerűen biztosítása gomb jobbra néz, vagy ez egy programozó a szokást a gépelés recv () annyiszor? Képezik a saját összeesküvés-elméletek (ismét jó SmallTalkot a felek).

Ez az, ahol belefutottam egy kis probléma írásakor saját Megnyerő programok. Csak a recv () jó, ha pontosan tudja, hogy mennyi adatot fog kapni (mint például egy játékban, ahol az első bájt lehet egy parancsot, és a következő bájt lehet egy paraméter, stb), de ha don ‘t tudni, mit csinálsz? Ha az adatok át Önhöz megszakítja egy új sor karakter (egy gyakori probléma a Java ügyfelek beszél C szerverek), akkor írj egy Readline () függvény mindent rögzíteni akár a karaktert. Itt van, amit használni:

char * readLine()

{

   vector theVector;

   char buffer;

   int bytesReceived;



   while (true)

   {

      bytesReceived = recv(theSocket, &buffer, 1, 0);

      if (bytesReceived <= 0)

         return NULL;



      if (buffer == '\n')

      {

         char *pChar = new char[theVector.size() + 1];

         memset(pChar, 0, theVector.size() + 1);



         for (int f = 0; f < theVector.size(); f++)

            pChar[f] = theVector[f];



         return pChar;

      } else {

         theVector.push_back(buffer);

      }

   }

}

A vektort alkalmazunk helyett egy tömb, mivel a tárolási helyet növelhető automatikusan, hogy megfeleljen az a vonal hosszát. Ha recv () függvény hibát jelez (bytesReceived kisebb, mint nulla), NULL vissza. Mivel ez egy lehetőség, telefonálási funkciókat kell biztosítani, hogy a húr visszatért Readline () érvényes használat előtt. Belül a hurok, egy char érkezik a konnektorból, és ha nem egy új sor karaktert, hozzáadjuk a vektor. Ha ez egy új sor karaktert, a tartalmát a vektor másolja be a C húr, és visszatért. A string nyilvánított egy char nagyobb, mint a vektor és memset () “Ted nullára, hogy a visszaadott sorban automatikusan NULL-terminált. Végződő húrok NULL megakadályozza szokatlan hibák és általában jó programozási gyakorlat.

Sem mutatja ezt ügyesen javított változata, amely támogatja a felbukkanó törlések és képes megváltoztatni az új sor karaktert könnyen:

// Kód eredetileg írta sem. Némileg módosított

// támogatja a MessageBox () API, hogy a logika olvashatóbb,

// igazítsa távolság, és megjegyzéseket fűzhetnek. Feladta engedélyével.



#define backKey '\b'					// letiltani backspaces, #define backKey NULL

#define newLine '\n'

#define endStr  '\0'



char *readLine(SOCKET s)

{

	vector theVector;

	char buffer;

	char *pChar;

	int bytesReceived;



	while (true)

	{

		bytesReceived = recv(s, &buffer, 1, 0);



		if (bytesReceived <= 0)

		{

			MessageBox(NULL, "recv() returned nothing.", "socketIndication", MB_OK);

			return NULL;

		}



		switch (buffer)

		{

			case backKey:			// Handle backspace

				if (theVector.size() > 0)

					theVector.pop_back();

				break;

			case endStr:			// Ha vége karakterlánc char elérte,

			case newLine:			// vagy ha a sor vége karakter elérte,

				pChar = new char[theVector.size() + 1];

				memset(pChar, 0, theVector.size() + 1);



				for (int f = 0; f < theVector.size(); f++)

					pChar[f] = theVector[f];

				return pChar;

				break;

			default:			// bármilyen rendszereschar

				theVector.push_back(buffer);

				break;

		}

	}

}

Leállás és aszinkron aljzatok

Egészen eddig a pontig már beszélünk blokkoló foglalatok, ahol egy funkció, mint elfogadni () korlátlan ideig várakozik a felhasználó kapcsolódni. A nem-blokkoló socket azonnal visszatér, amikor azt mondtuk, hogy tegyen valamit, akár egy sikeres eredmény, egy hiba, vagy semmi (jelezve, hogy lesz valami, hogy megkapja később). A hátránya, ez a típus, hogy neked kell manuálisan lekérdezni az aljzat, hátha eredményeként jött el minden funkció hívja. Akkor át egy sor aljzatok, hogy a select () függvény, hogy melyik is készen állnak az olvasás, írás, vagy visszatértek hibákat.

Funkciók aszinkron konnektorok is vissza azonnal, de megadhat egy üzenetet küld az ablakon eljárás, amikor egy meghatározott esemény történt. Például, akkor már az aljzat Levél SOCKET_GOTMSG üzenetet, amikor kap valamit. Általában ez okos hogy ellenőrizze a hibát (nehézkes, de szükséges), ha kap egy socket üzenetet elkerülje a felesleges problémákat később. Először nézzük meg, bizonyos funkciók fogjuk használni, hogy hozzanak létre egy aszinkron socket:

Nos, nézzük létre egy aszinkron socket:

// Kezdjük létrehozásával egy zászlót, hogy a Windows fogja használni, hogy lépjen kapcsolatba velünk, ha valami történik

#define THERE_WAS_A_SOCKET_EVENT	WM_USER + 100	// WM_USER is a base for custom messages

// Valahol a inicializáló kódot után CreateWindow (), nevezzük WSAAsyncSelect ()

WSAAsyncSelect ( theSocket, hwnd, THERE_WAS_A_SOCKET_EVENT, FD_READ | FD_WRITE | FD_CONNECT | ... );



// Ez több: Windows, kérem keressen meg az THERE_WAS_A_SOCKET_EVENT flag that I

// korábban meghatározott ott, amikor adatokat olvasni (FD_READ), vagy amikor szabad vagyok, hogy adatokat küldjön

// (FD_WRITE), vagy amikor már sikeresen kapcsolódott valaki (FD_CONNECT), vagy ha ... stb.

// A mi ablakot eljárás (a funkciót, amely kezeli az összes üzenetet, hogy a Windows küld az Ön app)

LRESULT WINAPI TheWindowProcedure ( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam )

{



	switch ( msg )

	{

		case THERE_WAS_A_SOCKET_EVENT:

			if ( WSAGETSELECTERROR ( lParam ) )

			{	// If an error occurred,

				closesocket ( theSocket );

				WSACleanup ();				// Shutdown Winsock

				return NETWORK_ERROR;

			}

			switch ( WSAGETSELECTEVENT ( lParam ) )

			{	// Mi történt, pontosan?

				case FD_READ:

					// Adatok fogadása

					break;

				case FD_WRITE:

					// Írja adatok
					break;

				case FD_CONNECT:

					// Csak csatlakoztatott szerver

					break;

				case ...				// Ugyanaz a beállítás, más zászlók

					break;

			}

			break;



		// Más esetben kimutatások logika, amely kezeli a többi Windows üzenetek



	}

}

Ne feledje, hogy nem lehet meghatározni egy üzenetet minden eseményt, mint SOCKET_GOTMSG a FD_READ majd SOCKET_CONNECTED a FD_CONNECT. Ez azért van, mert többször is felszólította, hogy WSAAsyncSelect (), hogy beállít minden zászlót törli a hatását az utolsó hívás WSAAsyncSelect ().

További oktatóanyagok és linkek

Azért írtam ezt a bemutatót 2000 decemberében, és a hét, vagy úgy év óta nem látta meg, így folyamatos a látogatók és a fejlesztéseket. Remélem, élvezettel olvasta, mint én élveztem írásban: Köszönjük, hogy a Johnnie Megnyerő bemutatója. A fenti csak egy rövid áttekintést a lehetőségeket elérheti keresztül Megnyerő, és mások végeztek egy sokkal jobb munkát végeznek, mint nekem szondázás a pontos részletek ebben a témában:
Fordította s http://johnnie.jerrata.com/winsocktutorial/

 

 

 

 

 

 

Home