Johnnie’sWinsockTutorial

ორ�?გ�?ნალურ�? გვერდ�? http://johnnie.jerrata.com/winsocktutorial/

 

თუ თქვენ შეგნებულად მ�?ვ�?და ჩემ�? Winsock tutorial, თქვენ, სავარაუდოდ, ნაპოვნ�? �?დეა საკუთარ�? პროგრამებ�? კომუნ�?კაც�?�?ს მეშვეობ�?თ �?ნტერნეტშ�?, როგორც მომხ�?ბლავ�? პერსპექტ�?ვა, როგორც მე მაქვს. ან, ალბათ, ვ�?ნმე �?პოვა პერსპექტ�?ვა თანაბრად სა�?ნტერესო და თქვენ უკვე დაევალა შემოტანა ამ ხედვ�?ს რეალობად. ორ�?ვე შემთხვევაშ�?, Winsock ქსელ�?ს სერვ�?ს�? და ამ tutorial დაგეხმარებათ მ�?საღწევად თქვენ�? მ�?ზნებ�?ს კომერც�?ულ�? საწარმო, უბრალოდ შე�?სწავლოს სფეროშ�? ქსელ�? პროგრამ�?რებ�?ს პ�?რად�? სარგებლობ�?სათვ�?ს, ან რამე შორ�?ს.

აქ არ�?ს �?ს, რაც ჩვენ გააშუქებს:

  • შექმნა მოსმენ�?ს ბუდე: გეძლევათ პატარა ჯარ�? ქსელ�?ს ფუნქც�?ებ�?, შეგვ�?ძლ�?ა ავაშენოთ პროგრამა, რომელ�?ც მოთმ�?ნებ�?თ ელოდება შემომავალ�? კავშ�?რებ�?? (დ�?ახ, შეგვ�?ძლ�?ა.)
  • მ�?ღებ�?ს საკუთარ�? კავშ�?რებ�?: �?მ�?ს გათვალ�?სწ�?ნებ�?თ, რამდენ�?მე დამატებ�?თ�? ფუნქც�?ებ�?, შეგვ�?ძლ�?ა შევქმნათ პროგრამა, რომელ�?ც წარმატებ�?თ კავშ�?რებ�? მოსმენ�?ს სერვერზე? (დ�?ახ, შეგვ�?ძლ�?ა.)
  • უფრო გაკვეთ�?ლებ�? და ბმულებ�?: რა რესურს�? არსებობს, ზემოთ და მ�?ღმა ამ tutorial? მე მონ�?შნეთ 3 რომ უნდა შევ�?ნარჩუნოთ თქვენ დაკავებულ�?, ხოლო (მას შემდეგ, რაც თქვენ უკვე მონელებულ�? ჩემ�? tutorial, რა თქმა უნდა :-).

მ�?უხედავად �?მ�?სა, რომ თქვენ შე�?ძლება �?ყოს და�?ნტერესებულ�?, რომ მ�?აღწ�?ოს, რომ awe-�?ნსპ�?რ�?რებ�?თ პუნქტ�?, რომელ�?ც თქვენ�? განცხადება წარმატებ�?თ, რაც მ�?ს�? პ�?რველ�? კავშ�?რ�?, უნდა �?ცოდეს, ცნებებ�? უკან კოდ�?. ცდ�?ლობენ, რათა თავ�?დან ავ�?ც�?ლოთ უბრალოდ მან�?პულ�?რებ�?ს მოცემულ�? კოდ�? ვარ�?ანტს თქვენ�? უშუალო საჭ�?როებებს და ამ�?ს ნაცვლად �?დენტ�?ფ�?ც�?რება მოთხოვნებს თქვენ�? განაცხად�? და მხოლოდ ამ�?ს შემდეგ განახორც�?ელოს, რაც, როგორც ჩანს, საუკეთესო გამოსავალ�?. რომ საკმარ�?ს�?ა ჩემ�? Zen, პროგრამულ�? უზრუნველყოფა-შემუშავება რჩევა ახლა; მოდ�?თ, ნუ ზოგ�?ერთ�? ქსელურ�? პროგრამ�?რებ�?ს…

Feel free to download მთელ�? სამეურვეო კოდ�? ჩამონათვალ�?. გახსოვდეთ, რომ რა�?მე კოდ�? წარმოდგენ�?ლ�? ეს გაკვეთ�?ლ�? უნდა �?ყოს დაკავშ�?რებულ�? Winsock ბ�?ბლ�?ოთეკა, როგორც წეს�?, wsock32.lib ან რამე ასეთ�?ვე დასახელდა. გარდა ამ�?სა, როდესაც გამოყენებ�?თ კოდ�? ზუსტად �?სე, როგორც წარმოადგ�?ნა სამეურვეო საკუთარ�? IDE (Dev-C++, Microsoft VC++, C++ Builder, და ა. შ.), ა�?რჩ�?ეთ აშენება Windows პროექტ�? WinMain() , რათა თავ�?დან ავ�?ც�?ლოთ შეცდომებ�?.

შექმნა მოსმენ�?ს Socket

პროგრამებ�? მომსახურება გარეთ მანქანებ�? უწოდებენ სერვერებ�?. სერვერზე პროგრამებ�? მოუსმ�?ნეთ კლ�?ენტებს �?ნ�?ც�?ალ�?ზაც�?�?სას ერთ�? ან მეტ�? მოსმენ�?ს სოკეტებ�?ს. როდესაც კლ�?ენტ�? უკავშ�?რდება ერთ�? ასეთ�? მოსმენ�?ს სოკეტებ�?ს, სერვერზე �?ღებს შეტყობ�?ნება, Winsock, ადასტურებს კავშ�?რ�?, და �?წყება დ�?სპეტჩერ�?ზაც�?�?ს და ჩაჭრა შეტყობ�?ნებებ�? და ახალ�? კლ�?ენტ�?. ალბათ ყველაზე მარტ�?ვ�? მეთოდ�?, რომელ�?ც სერვერებ�? სახელურ�? მრავალჯერად�? კლ�?ენტებს არ�?ს spawn ახალ�? თემა თ�?თოეულ კლ�?ენტთან დაკავშ�?რებ�?თ. ამ სერვერზე მოდელ�? ყველაზე ხშ�?რად �?ყენებს დაბლოკვა სოკეტებ�?ს, რომელ�?ც პაუზ�?ს დროებ�?თ დაველოდოთ შემომავალ�? მონაცემებ�?ს, ახალ�? კავშ�?რ�?, და სხვა ქსელ�?ს მოვლენებ�?. პ�?რველ რ�?გშ�?, მოდ�?თ �?დენტ�?ფ�?ც�?რება გარკვეულ�? სტრუქტურებ�?ს ჩვენ უნდა �?ნ�?ც�?ალ�?ზაც�?ა დაბლოკვა ბუდე:

  • WSADATA: ეს სტრუქტურა არ�?ს მეორად�?, რომ შეკ�?თხვ�?ს ოპერაც�?ულ�? ს�?სტემ�?ს �?ს ვერს�?ა, Winsock ჩვენ�? კოდ�? მო�?თხოვს. განცხადება მოუწოდებს WSAStartup() ვრთავ სწორ�? Winsock DLL.
  • SOCKET: ობ�?ექტ�? (ფაქტობრ�?ვად, ეს გან�?საზღვრება, როგორც u_int, unsigned integer, winsock.h—კარგ�?, ვ�?ც�?, smalltalk პარტ�?ებ�?ს) მ�?ერ გამოყენებულ�? პროგრამებ�? შესანახად socket სახელურ�?.
  • SOCKADDR_IN: პროგრამა �?ყენებს ამ სტრუქტურას უნდა მ�?უთ�?თოთ, თუ როგორ socket უნდა �?მოქმედონ. SOCKADDR_IN შე�?ცავს სფეროებშ�? IP მ�?სამართ�?ს და პორტ�?ს ნომერ�?:
struct sockaddr_in

{

 მოკლე sin_family; // ოქმ�? ტ�?პ�?

 u_short sin_port; // პორტ�?ს ნომერ�? socket

 struct in_addr sin_addr; // IP მ�?სამართ�?

 char sin_zero[8]; // გამოუყენებელ�?

};

პ�?რველ�? საველე ოქმ�? ტ�?პ�?, რომელ�?ც, როგორც წეს�?, AF_INET (TCP/IP). როგორც მოსმენ�?ს socket არ არ�?ს და�?ნტერესებულ�?, ქსელ�?ს მ�?სამართ�? მანქანა, რომელშ�?ც �?ს ცხოვრობს, Winsock ავტომატურად ან�?ჭებს IP მ�?სამართ�?ს და პორტ�?ს ნომერ�? მოსმენ�?ს სოკეტებ�?ს საფუძველზე შექმნა.

ჩვენ უნდა ავაშენოთ ჩვენ�? პ�?რველ�? მოსმენ�?თ სერვერზე ზემოთ სტრუქტურებ�? და პატარა არმ�?ა ქსელ�?ს ფუნქც�?ებ�?:

#include <windows.h>

#include <winsock.h>

#include <stdio.h>



#განსაზღვრავს NETWORK_ERROR -1

#განსაზღვრავს NETWORK_OK 0



ბათ�?ლად ReportError(int, const char *);





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

{

 ს�?ტყვა sockVersion;

 WSADATA wsaData;

 int nret;



 sockVersion = MAKEWORD(1, 1); // ჩვენ გვ�?ნდა, Winsock ვერს�?ა 1.1





 // ჩვენ ვ�?წყებთ �?ნ�?ც�?ალ�?ზაც�?�?სას Winsock

 WSAStartup(sockVersion, და wsaData);





 // შემდეგ�?, შექმნა მოსმენ�?ს socket

 SOCKET listeningSocket;



 listeningSocket = socket(AF_INET, // წავ�?დეთ მეტ�? TCP/IP

 SOCK_STREAM,  // ეს არ�?ს stream-ორ�?ენტ�?რებულ�? socket

 IPPROTO_TCP); // გამო�?ყენოთ TCP ვ�?დრე UDP



 თუ (listeningSocket == INVALID_SOCKET)

{

 nret = WSAGetLastError(); // Get უფრო დეტალურ�? შეცდომა

 ReportError(nret, "socket()"); // ანგარ�?შ�? შეცდომა ჩვენ�? საბაჟო ფუნქც�?ა



 WSACleanup(); // გამორთვა Winsock

 დაბრუნება NETWORK_ERROR; // დაბრუნება შეცდომა ღ�?რებულება

}





 // გამო�?ყენოთ SOCKADDR_IN struct შეავსოთ მ�?სამართზე �?ნფორმაც�?ა

 SOCKADDR_IN serverInfo;



 serverInfo.sin_family = AF_INET;

 serverInfo.sin_addr.s_addr = INADDR_ANY; // მას შემდეგ, რაც ეს სოკეტ�? არ�?ს მოსმენ�?ს კავშ�?რებ�?,

  // ნებ�?სმ�?ერ�? ადგ�?ლობრ�?ვ�? მ�?სამართ�? გააკეთებს

 serverInfo.sin_port = htons(8888); // გადა�?ყვანოთ რ�?ცხვ�? 8888 ქსელშ�?-byte მ�?ზნ�?თ

 // და ჩადეთ პორტ�? სფეროშ�?





 // სავალდებულოა socket ჩვენ�? ადგ�?ლობრ�?ვ�? სერვერ�?ს მ�?სამართ�?

 nret = სავალდებულოა(listeningSocket, (LPSOCKADDR) და serverInfo, sizeof(struct sockaddr));



 თუ (nret == SOCKET_ERROR)

{

 nret = WSAGetLastError();

 ReportError(nret, "bind()");



WSACleanup();

 დაბრუნება NETWORK_ERROR;

}





 / / , რათა socket მოუსმ�?ნეთ

 nret = მოუსმ�?ნეთ(listeningSocket, 10); // Up to 10 კავშ�?რებ�? შე�?ძლება ველოდოთ ნებ�?სმ�?ერ

 // ერთ�? დრო უნდა მ�?�?ღოს()'ედ



 თუ (nret ==SOCKET_ERROR)

{

 nret = WSAGetLastError();

 ReportError(nret, "listen()");



WSACleanup();

 დაბრუნება NETWORK_ERROR;

}





 // დაველოდოთ კლ�?ენტ�?

 SOCKET theClient;



 theClient = მ�?�?ღოს(listeningSocket,

 NULL, // არააუც�?ლებელ�?, მ�?სამართ�? SOCKADDR_IN struct

 NULL); // არააუც�?ლებელ�?, მ�?სამართ�? ცვლად�?, რომელ�?ც შე�?ცავს

 // sizeof ( struct SOCKADDR_IN )



 თუ (theClient == INVALID_SOCKET)

{

 nret = WSAGetLastError();

 ReportError(nret, "მ�?�?ღოს()");



WSACleanup();

 დაბრუნება NETWORK_ERROR;

}





 // გააგზავნოთ და მ�?�?ღოთ კლ�?ენტს და საბოლოოდ,

closesocket(theClient);

closesocket(listeningSocket);





 // გამორთვა Winsock

WSACleanup();

 დაბრუნება NETWORK_OK;

}





ბათ�?ლად ReportError(int errorCode, const char *whichFunc)

{

 char errorMsg[92]; // აცხადებენ, ბუფერულ�? გამართავს

 // გენერ�?რებულ�? შეცდომა



 ZeroMemory(errorMsg, 92); // ავტომატურად NULL-შეწყვ�?ტოს string



 // შემდეგ�? ხაზ�? ასლებ�? ფრაზა, whichFunc string, და რ�?ცხვ�? errorCode შევ�?და ბუფერულ�?

 sprintf(errorMsg, "ზარ�? %s დაბრუნდა შეცდომა %d!", (char *)whichFunc, errorCode);



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

}

ერთ�? რამ, თქვენ მაშ�?ნვე შეამჩნევთ შესახებ კოდ�? არ�?ს თანხ�?ს ძალ�?სხმევა შევ�?და შემოწმებ�?ს შეცდომა. როდესაც შეცდომა ხდება, კოდ�? �?ძენს კონკრეტულ�? შეცდომ�?ს კოდ�? ერთად WSAGetLastError() და მაღაზ�?ებ�? შედეგ�? nret. შეცდომა კოდ�? არ�?ს მაშ�?ნ გაგზავნ�?ლ�? ერთად ს�?მებ�?ან�? მ�?უთ�?თებს, სახელ�? ვერ ფუნქც�?ა საბაჟო ფუნქც�?ა სახელად ReportError(). �?ქ, შეცდომა არ�?ს აშენებულ�? და აჩვენა მომხმარებელს ზარ�? MessageBox(), რომელ�?ც არ�?ს ნაწ�?ლ�? სტანდარტულ�? WinAPI. მაგალ�?თად, ჰქონდა მოუსმ�?ნეთ() ვერ შეცდომა კოდ�? 10093 (გან�?საზღვრება, როგორც WSANOTINITIALISED), მზა შეცდომა string �?ქნება “ზარ�?ს მოსასმენად() დაბრუნდა შეცდომა 10093!”. თქვენ, გონ�?ვრულ�? შემქმნელ�?, მაშ�?ნ ეძებოთ კოდ�? და აღმოაჩენთ, რომ შეცდომა მოხდა �?მ�?ტომ, რომ წარმატებულ�? ზარ�? WSAStartup() ჯერ კ�?დევ არ ყოფ�?ლა.

Aleksandar პავლოვ�?ს გაფართოვდა ეს ReportError() მო�?ცავს აღწერ�?ლობა დაახლოებ�?თ ათეულ�? გავრცელებულ�? socket შეცდომებ�?. გამოყენებ�?თ მ�?ს�? განახლებულ�? ვერს�?ა, თქვენ აღარ უნდა საძ�?ებელ�? რა კოდ�? �?მას ნ�?შნავს, და თქვენ�? პროგრამ�?თ ხდება ბევრად უფრო მოსახერხებელ�? ძალ�?ან ცოტა ძალ�?სხმევა თქვენ�? მხრ�?დან.

ასევე არ�?ს განსაზღვრავს �?ყ�?დება NETWORK_ERROR და NETWORK_OK. ეს შე�?ძლება �?ყოს სასარგებლო, როდესაც შემოწმებ�?ს დაბრუნება არც საკუთარ�? ქსელ�?ს ფუნქც�?ებ�?. თუ თქვენ�? ფუნქც�?ებ�? დაბრუნდა ერთ�? ამ ღ�?რებულებებ�?ს ნომრებზე ფუნქც�?ა შე�?ძლება შეასრულოს მარტ�?ვ�? თანასწორობ�?ს ტესტ�? გამოავლ�?ნოს ნებ�?სმ�?ერ�? შეცდომებ�?: თუ (myNetworkingFunction() == NETWORK_ERROR) {…}. ნომრებზე ფუნქც�?ა შე�?ძლება შემდეგ მ�?�?ღოს კონკრეტულ�? კოდ�? WSAGetLastError() და handle შეცდომა შესაბამ�?სად. საბოლოო ჯამშ�?, ახორც�?ელებს კარგ�? შეცდომა გატარება სქემა ახლა დაგ�?ზოგავთ თქვენ ბევრ�? დღ�?ს ან კვ�?რ�?ს განვ�?თარებ�?ს დროს, როგორც თქვენ მყ�?ს�?ერად ვ�?ც�? რატომ, თქვენ�? პროგრამა ვერ შეძლო.

გარდა �?მ�?სა, რომ დაბრუნებ�?ს ახალ�? კლ�?ენტ�? კავშ�?რ�?, მ�?�?ღოს() საშუალებას სერვერზე ამონაწერ�? �?ნფორმაც�?ა კლ�?ენტ�?ს შესახებ, ვ�?დრე მეშვეობ�?თ მეთოდებ�? მო�?თხოვს დამატებ�?თ�? ფუნქც�?ა ზარებ�? ან დრო (რომელ�?ც შე�?ძლება გახდეს საკ�?თხ�? ამ თამაშ�?ს სერვერებ�?, სადაც ს�?ჩქარე მ�?�?ღოს loop განსაკუთრებ�?თ კრ�?ტ�?კულ�?). �?სარგებლოს ამ ფუნქც�?ონ�?რება, გა�?ვლ�?ს მ�?სამართ�? sockaddr_in struct როლებშ�? რათა sockaddr მაჩვენებელ�?, ანუ (LPSOCKADDR) და aSockaddrInStructure. გარდა ამ�?სა, განვაცხადო, მთელ�? ცვლად�?, მ�?თ�?თებულ�? ღ�?რებულება int, რომ sizeof, რომ sockaddr struct, და აკეთებს მ�?სამართ�? რ�?ცხვ�?, როგორც მესამე პარამეტრ�?. თუ მ�?სამართ�?, �?ნფორმაც�?ა უნდა �?ყოს დაბრუნდა მას შემდეგ, რაც ფუნქც�?ა ზარ�?, ს�?გრძ�?ს პარამეტრ�? უნდა �?ყოს.

jdarnold გვაფრთხ�?ლებს, რომ არ მჯერა MSDN დაკავშ�?რებ�?თ დოკუმენტაც�?�?ს ეს მესამე პარამეტრ�?: “MSDN docs გულ�?სხმობს, თქვენ არ უნდა გა�?აროს addrlen, რომ ეს არ�?ს პ�?რველ�? სურვ�?ლ�?სამებრ გამომავალ�? პარამეტრ�?, მაგრამ �?ს�?ნ�? არასწორ�?ა. შემომავალ�? �?ს ამბობს, რამდენ�? ბა�?ტ�? არ�?ან sockaddr buffer, და გამავალ�? [Winsock] ავსებს რამდენ�? [Winsock] გამოყენებულ�?. თუ თქვენ გა�?ვლ�?ს ნულოვან�? როგორც len, [Winsock] არ შეეხოთ buffer.”

ეს არ არ�?ს ბევრ�? სერვერ�?, რადგან მას ელოდება მხოლოდ ერთ�? მომხმარებლ�?ს დაკავშ�?რება და შემდეგ ეგრევე �?რთვება, მაგრამ ეს არ�?ს ყველაზე ძ�?რ�?თად�? დ�?ზა�?ნ�?. უბრალოდ გარკვევა რამ, ზარ�? WSAStartup() მოყვება ს�?ტყვა მ�?უთ�?თებს, თუ რა ვერს�?ა გსურთ ჩატვ�?რთვა (ამ შემთხვევაშ�? ეს არ�?ს 1.1) და მ�?სამართ�? WSADATA სტრუქტურა. შემდეგ�?, ჩვენ დაფარავს როგორ აკავშ�?რებს სხვა კომპ�?უტერებ�?.

მ�?ღებ�?ს საკუთარ�? კავშ�?რებ�?

შექმნა socket დაკავშ�?რება ვ�?ნმე �?ყენებს ყველაზე �?გ�?ვე ფუნქც�?ებ�?, გარდა HOSTENT struct:

  • HOSTENT: სტრუქტურა, მეორად�?, რომ გ�?თხრათ, სოკეტ�?, რომელ�?ც კომპ�?უტერულ�? და პორტ�?ს დაკავშ�?რება. ამ სტრუქტურებშ�? ხშ�?რად, როგორც ჩანს, LPHOSTENT ცვლადებ�?, რომლებ�?ც მხოლოდ მ�?თ�?თებას HOSTENT სტრუქტურებშ�?. როგორც თქვენ კოდ�? Windows, თქვენ ზოგადად ნახავთ, რომ ნებ�?სმ�?ერ�? მონაცემთა ტ�?პ�? წ�?ნ უძღოდა LP აღნ�?შნავს, რომ ტ�?პ�? არ�?ს რეალურად მომცეთ “ბაზა” ტ�?პ�? (მაგალ�?თად, LPCSTR არ�?ს მომცეთ C string, ასევე ცნობ�?ლ�?ა, როგორც char *).

ასე რომ, მოდ�?თ, მ�?�?ღოს უფლება კოდ�?:

#include <windows.h>

#include <winsock.h>

#include <stdio.h>



#განსაზღვრავს NETWORK_ERROR -1

#განსაზღვრავს NETWORK_OK 0



ბათ�?ლად ReportError(int, const char *);





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

{

 ს�?ტყვა sockVersion;

 WSADATA wsaData;

 int nret;



 sockVersion = MAKEWORD(1, 1);





 // ვრთავ Winsock, როგორც ადრე

 WSAStartup(sockVersion, და wsaData);





 // Store �?ნფორმაც�?ა სერვერზე

 LPHOSTENT hostEntry;



 hostEntry = gethostbyname("www.yahoo.com"); // სასურველ�? სერვერ�?ს მ�?ერ მ�?ს�? სახელ�?;

 // კ�?დევ ერთ�? ვარ�?ანტ�?:gethostbyaddr()



 თუ (!hostEntry)

{

 nret = WSAGetLastError();

 ReportError(nret, "gethostbyname()"); // ანგარ�?შ�? შეცდომა, როგორც ადრე



WSACleanup();

 დაბრუნება NETWORK_ERROR;

}





 // შევქმნათ socket

 SOCKET theSocket;



 theSocket = socket(AF_INET, // წავ�?დეთ მეტ�? TCP/IP

 SOCK_STREAM, // ეს არ�?ს stream-ორ�?ენტ�?რებულ�? socket

 IPPROTO_TCP); // გამო�?ყენოთ TCP ვ�?დრე UDP



 თუ (theSocket == INVALID_SOCKET)

{

 nret = WSAGetLastError();

 ReportError(nret, "socket()");



WSACleanup();

 დაბრუნება NETWORK_ERROR;

}





 // შეავსოთ SOCKADDR_IN struct ერთად მ�?სამართ�?�?ნფორმაც�?ა

 SOCKADDR_IN serverInfo;



 serverInfo.sin_family = AF_INET;



 // ამ ეტაპზე, ჩვენ წარმატებ�?თ წაკ�?თხვ�?ს თარ�?ღ�?: სას�?ცოცხლო �?ნფორმაც�?ა სერვერზე,

 // მათ შორ�?ს ჰოსთ�?ს, მაგალ�?თ�?, და IP მ�?სამართებ�?. დაველოდოთ; როგორ შე�?ძლება ერთ�?

 // კომპ�?უტერულ�? მქონდეს მ�?სამართებ�?, და ზუსტად რა არ�?ს შემდეგ�? ხაზ�? აკეთებს?

 // ნახოთ ახსნა ქვემოთ.



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



 serverInfo.sin_port = htons(80); // ცვლ�?ლება ქსელ�?-byte მ�?ზნ�?თ და

 // insert into პორტ�? სფეროშ�?





 // სერვერთან დაკავშ�?რება

 nret = დაკავშ�?რება(theSocket,

 (LPSOCKADDR) და serverInfo,

 sizeof(struct sockaddr));



 თუ (nret == SOCKET_ERROR)

{

 nret = WSAGetLastError();

 ReportError(nret, "connect()");



WSACleanup();

 დაბრუნება NETWORK_ERROR;

}





 // წარმატებ�?თ დაკავშ�?რებულ�?!





 // Send/receive, მაშ�?ნ წმენდა:

closesocket(theSocket);

WSACleanup();

}





ბათ�?ლად ReportError(int errorCode, const char *whichFunc)

{

 char errorMsg[92]; // აცხადებენ, ბუფერულ�? გამართავს

 // გენერ�?რებულ�? შეცდომა



 ZeroMemory(errorMsg, 92); // ავტომატურად NULL-შეწყვ�?ტოს string



 // შემდეგ�? ხაზ�? ასლებ�? ფრაზა, whichFunc string, და რ�?ცხვ�? errorCode შევ�?და ბუფერულ�?

 sprintf(errorMsg, "ზარ�? %s დაბრუნდა შეცდომა %d!", (char *)whichFunc, errorCode);



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

}

ყველაზე რთულ�? ხაზ�? ჩამონათვალ�? არ�?ს შემდეგ�?:

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

�?მ�?ტომ, რომ �?გ�? ასრულებს რამდენ�?მე ოპერაც�?ებ�?—ერთ�? მათგან�? შედარებ�?თ დამალულ�?—ერთდროულად. ავ�?ღოთ �?ს გარდა ეტაპობრ�?ვად:

“H_addr_list წევრ�? HOSTENT struct, ძ�?რ�?თადად, გან�?საზღვრება, როგორც char **h_addr_list, რომელ�?ც მას�?ვ�? ს�?მებ�?, ან char *’s. gethostbyname() განსაზღვრულ�? და გადაწერა ყველა ცნობ�?ლ�? მ�?სამართებ�? სერვერზე შევ�?და ამ ს�?აშ�?. თუმცა, ეს კონცეფც�?ა სხვადასხვა მ�?სამართებ�? ფუნდამენტურად აზრ�?? ს�?ნამდვ�?ლეშ�?, ეს ასეა. თქვენს კომპ�?უტერშ�?, ფაქტობრ�?ვად, უკვე მას�?ვ�? ზოგად�? ქსელ�?ს მ�?სამართებ�?. თქვენ�? �?ნტერნეტ მ�?სამართ�? შე�?ძლება �?ყოს 205.182.67.96, თქვენ�? LAN მ�?სამართ�? შე�?ძლება �?ყოს 10.0.0.2, და ყველა კომპ�?უტერ�?, რომელ�?ც ფანჯრებ�? არ�?ს დამონტაჟებულ�?, ბუნებრ�?ვ�?ა, აქვს “loopback” მ�?სამართ�? 127.0.0.1, გამო�?ყენება კომპ�?უტერულ�? �?ხ�?ლეთ თავად ლოკალურ ქსელშ�?. �?გ�?ვე კონცეფც�?ა ეხება სფეროშ�? �?ნტერნეტ მ�?სამართებ�? ან IP-ს, რ�?ს გამოც ს�?აშ�? არ�?ს საჭ�?რო, ვ�?დრე საცავ�? ერთ�? მ�?სამართ�?. გა�?თვალ�?სწ�?ნეთ, რომ სასურველ�? მ�?სამართ�?, რომ არ�?ს, ყველაზე ხელმ�?საწვდომ�? მ�?სამართ�?, ყოველთვ�?ს გადაწერა შევ�?და პ�?რველ�? ელემენტ�? ს�?აშ�?, რასაც მოჰყვა მეორე ამჯობ�?ნა ან სხვა მ�?სამართებ�?.

რა *hostEntry->h_addr_list აკეთებს? თქვენ ალბათ მ�?ხვდებ�?, რომ პატ�?ვ�?სცემ�?ს ნ�?შნად ოპერატორ�? (*) გამო�?ყენება წვდომ�?ს ერთ მ�?სამართ�? ს�?აშ�?. თუმცა, ვერ უზრუნველყოფს კონკრეტულ�? მაჩვენებელ�?, dereference ოპერაც�?ა ავტომატურად ავლენს პ�?რველ�?, სასურველ�? მ�?სამართ�?. რომ კონკრეტულ�? მონაკვეთ�?ს უდრ�?ს *hostEntry->h_addr_list[0], რომელ�?ც არ�?ს გარანტ�?რებულ�?, რომ არსებობს მას შემდეგ, სერვერზე უნდა ჰქონდეს მ�?ნ�?მუმ ერთ�? მ�?სამართ�?.

შემდეგ�?, char * დაბრუნდა dereferencing ოპერაც�?ა არ�?ს მ�?ცემულ�? შევ�?და in_addr * ან LPIN_ADDR. და ბოლოს, კ�?დევ ერთ�? პარად�?გმებ�?, ტერმ�?ნოლოგ�?ურ�? ოპერაც�?ა ხორც�?ელდება დაბრუნებას in_addr struct მოხსენ�?ებულ�? მაჩვენებელ�?, რომელ�?ც შე�?ძლება მხოლოდ hold ერთ�? მ�?სამართ�?. შედეგად in_addr struct არ�?ს მაშ�?ნ ენ�?ჭება serverInfo.sin_addr. მომდევნო connect() �?ღებს ერთ მ�?სამართ�?, როგორც პარამეტრ�?, როდესაც ფორმ�?რებ�?ს კავშ�?რ�? სერვერზე.

თუ სერვერ�?ს IP მ�?სამართ�? არ�?ს ცნობ�?ლ�?, მოქმედ�? HOSTENT შე�?ძლება �?ყოს მ�?ღებულ�? გამოყენებ�?ს gethostbyaddr() (როგორც ეწ�?ნააღმდეგებოდა gethostbyname() გამო�?ყენება წ�?ნა ჩამონათვალ�?):

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);



თუ (!hostEntry)

{

 // სახელურ�? შესაბამ�?სად

}

ამ შემთხვევაშ�?, inet_addr() არ�?ს გამოყენებულ�? ასლ�? ს�?მებ�?ან�? აღმნ�?შვნელ�? IP მ�?სამართ�? პ�?რდაპ�?რ in_addr struct. ამ�?ს შემდეგ, მ�?სამართ�? struct არ�?ს მ�?ცემულ�? შევ�?და const char * როგორც ამას gethostbyaddr(). ორ�?ვე მეთოდ�? არ�?ს მოხსენ�?ებულ�?, როგორც მოგვარებაშ�? სერვერ�?ს მ�?სამართ�?, რადგან Winsock ბრუნდება სრულ�? მ�?სამართ�? ჩანაწერებ�? ნაწ�?ლობრ�?ვ�? �?ნფორმაც�?ა.

რამდენ�?მე დამატებ�?თ�? შენ�?შვნებ�?: port 80 �?ყო გამოყენებულ�?, უბრალოდ �?მ�?ტომ, რომ �?ნტერნეტ ვებ გვერდ�? გზავნ�?ლებ�? მოხდეს მეტ�?, რომ პორტ�?. თუ �?ყო გაგზავნას ს�?მებ�?ან�? სერვერზე მოთხოვნ�?ს კონკრეტულ�? ფა�?ლ�? და ცდ�?ლობენ მ�?�?ღონ რაღაც უკან, ნეტავ, აქვს ძალ�?ან მარტ�?ვ�? web browser. რა თქმა უნდა, რომ ტექსტ�? უნდა შე�?ცავდეს სრულ HTTP ბრძანება. ეს არ�?ს დ�?დ�?, რომ ჩვენ შე�?ძლება მოუსმ�?ნოს და დაკავშ�?რება სხვა კომპ�?უტერებ�?, მაგრამ საკომუნ�?კაც�?ო ასევე მო�?ცავს გაგზავნ�?ს და მ�?ღებ�?ს.

გაგზავნ�?ს და მ�?ღებ�?ს

გაგზავნ�?ს ს�?ფრთხ�?ლ�?თ, მოხერხებულად საკმარ�?ს�?, send() ფუნქც�?ა:

int გაგზავნას(

 SOCKET s,

 const char * შორს buf,

 int len,

 int დროშებ�?

);

ძ�?რ�?თადად თქვენ, რომ ასლ�?, რაც უნდოდა, into a buffer და გამოყენება send() ფუნქც�?ა დაკავშ�?რებულ�?ა ბუდე, რათა მონაცემებ�?ს წასვლა სხვა დასასრულ�?:

char buffer[256]; // გამოცხადებ�?ს stack buffer

char *ბუფერულ�? = new char[256]; // ან ბევრ�?



ZeroMemory(ბუფერულ�?, 256);

strcpy(ბუფერულ�?, "ვ�?ტყვ�?, ეს არ�?ს მნ�?შვნელოვან�? მონაცემებ�?.");



nret = გაგზავნას(theSocket,

buffer,

 strlen(ბუფერულ�?), // გა�?თვალ�?სწ�?ნოთ, რომ ეს განსაზღვრავს ს�?გრძეზე ს�?მებ�?ან�?; არ

 // ზომა მთელ�? ბუფერულ�?

 0); // ყველაზე ხშ�?რად არ�?ს ნულოვან�?, მაგრამ ვხედავ MSDN სხვა ვარ�?ანტ�?



delete [] ბუფერ�?; // თუ და მხოლოდ თუ ბევრ�? დეკლარაც�?ა �?ყო გამოყენებულ�?,



თუ (nret == SOCKET_ERROR)

{

 // მ�?�?ღოს კონკრეტულ�? კოდ�?

 // სახელურ�? შესაბამ�?სად

 დაბრუნება NETWORK_ERROR;

} else {

 // nret შე�?ცავს რაოდენობ�?ს ბა�?ტს გაგზავნ�?ლ�?

}

მ�?ღება არ�?ს �?გ�?ვე პროცეს�?, უკან:

char buffer[256]; // დასტ�?ს

char *ბუფერულ�? = new char[256]; // ან ბევრ�?



nret = recv(theSocket,

buffer,

 256,//, სრულ�? ზომა ბუფერულ�?

0);



delete [] ბუფერ�?; // მან�?პულ�?რება buffer, მაშ�?ნ წაშალე, თუ და მხოლოდ თუ

 // ბუფერულ�? �?ყო გამოყოფ�?ლ�? ბევრ�?



თუ (nret == SOCKET_ERROR)

{

 // მ�?�?ღოს კონკრეტულ�? კოდ�?

 // სახელურ�? შესაბამ�?სად

 დაბრუნება NETWORK_ERROR;

} else {

 // nret შე�?ცავს რაოდენობ�?ს ბა�?ტს მ�?�?ღო

}

რა სა�?ნტერესოა, უნდა აღ�?ნ�?შნოს, რომ არსებობს ღ�?ლაკს პანელ�? Microsoft Outlook შეაფასა “გაგზავნას/Recv.” “მ�?�?ღოს” შემოკლებ�?თ “Recv” , უბრალოდ, უნდა უზრუნველყოს ღ�?ლაკს გამო�?ყურება უფლება, ან ეს programmer-�?ს ჩვევა საწყ�?ს�? აკრეფა recv() �?მდენჯერ? ფორმა საკუთარ�? შეთქმულებ�?ს თეორ�?ებ�? (კ�?დევ ერთხელ, კარგ�? smalltalk პარტ�?ებ�?).

ეს არ�?ს სადაც მე შეუვარდნენ პატარა პრობლემა, როდესაც წერა ჩემ�? საკუთარ�? Winsock პროგრამებ�?. უბრალოდ გამოყენებ�?თ recv() არ�?ს დ�?დ�?, როდესაც თქვენ �?ც�?თ ზუსტად რამდენ�? მონაცემებ�? თქვენ გექნებათ მ�?ღება (ასეთ�?, როგორც თამაშ�?, სადაც პ�?რველ�? ბა�?ტ�? შე�?ძლება ბრძანება და მომდევნო byte �?ყოს პარამეტრ�? და ა. შ.), მაგრამ როცა არ �?ც�?, რა ვქნათ? თუ მონაცემებ�? თქვენ მ�?ღებ�?ს შეწყვეტ�?სას მ�?ერ newline ხას�?ათ�? (საერთო პრობლემა Java კლ�?ენტებს საუბარ�? C სერვერებ�?), თქვენ შეგ�?ძლ�?ათ დაწეროთ readLine() ფუნქც�?�?ს ხელშ�? ყველაფერ�?, რომ ხას�?ათ�?. ა�? რა მე:

char * readLine()

{

 vectortheVector;

 char buffer;

 int bytesReceived;



 while (true)

{

 bytesReceived = recv(theSocket, და ბუფერულ�?, 1, 0);

 თუ (bytesReceived <= 0)

 return NULL;



 თუ (ბუფერულ�? == '\n')

{

 char *pChar = new char[theVector.ზომა() + 1];

 memset(pChar, 0, theVector.ზომა() + 1);



 for (int f = 0; f < theVector.ზომა(); ვ++)

 pChar[f] = theVector[f];



 დაბრუნება pChar;

 } else {

theVector.push_back(ბუფერულ�?);

}

}

}

ვექტორ�? არ�?ს გამოყენებულ�? ნაცვლად მას�?ვ�?, რადგან მ�?ს�? შენახვა ფართ�? შე�?ძლება გა�?ზარდოს ავტომატურად ვარ�?ანტს ხანგრძლ�?ვობა ხაზ�?. თუ recv() დააბრუნებს შეცდომ�?ს (მ�?თ�?თებულ�?ა bytesReceived მ�?მდ�?ნარეობს ნაკლებ�?ა, ვ�?დრე ნულოვან�?), NULL დაბრუნდა. რადგან ეს არ�?ს შესაძლებლობა, მოუწოდებს ფუნქც�?ებ�? უნდა უზრუნველყოს, რომ string დაბრუნდა readLine() მოქმედებს ადრე გამოყენება. შ�?გნ�?თ loop, ერთ�? char არ�?ს მ�?ღებულ�? ბუდე და, თუ არ არ�?ს newline ხას�?ათ�?, დასძ�?ნა, რომ ვექტორ�?. თუ ეს არ�?ს newline ხას�?ათ�?, შ�?ნაარს�? ვექტორ�? არ�?ს გადაწერ�?ლ�? შევ�?და C ს�?მებ�?ან�? და დაბრუნდა. ს�?მებ�?ან�? არ�?ს დეკლარ�?რებულ�? უნდა �?ყოს ერთ�? char უფრო დ�?დ�?, ვ�?დრე ვექტორ�? და memset()’ted ნულოვან�? �?სე, რომ დაბრუნდა line ავტომატურად NULL-წყდება. დამთავრებულ�? ს�?მებ�? NULL ხელს უშლ�?ს უჩვეულო შეცდომებ�? და, ზოგადად, კარგ�? პროგრამ�?რებ�?ს პრაქტ�?კა.

და არც წარმოადგენს ეს ჭკვ�?ანურად გაუმჯობესებულ�? ვერს�?ა მხარდაჭერა backspaces და უნარ�? შეცვალოს newline ხას�?ათ�? მარტ�?ვად:

// კოდ�? თავდაპ�?რველად დაწერ�?ლ�? და არც. შეცვლ�?ლ�?ა ოდნავ

// მხარდაჭერა MessageBox() API, რათა ლოგ�?კა უფრო �?კ�?თხება,

// გასწორება �?ნტერვალ�?, და დაამატეთ კომენტარ�?. გამოგზავნ�?ლ�?ა ნებართვ�?თ.



#განსაზღვრავს backKey '\b' // გამორთოთ backspaces, #define backKey NULL

#განსაზღვრავს newLine '\n'

#განსაზღვრავს endStr '\0'



char *readLine(SOCKET s)

{

 vectortheVector;

 char buffer;

 char *pChar;

 int bytesReceived;



 while (true)

{

 bytesReceived = recv(s, და ბუფერულ�?, 1, 0);



 თუ (bytesReceived <= 0)

{

 MessageBox(NULL, "recv() დაბრუნდა არაფერ�?.", "socketIndication", MB_OK);

 return NULL;

}



 switch (ბუფერულ�?)

{

 შემთხვევაშ�? backKey: // სახელურ�? უკუსვლ�?ს

 თუ (theVector.ზომა() > 0)

theVector.pop_back();

შესვენება;

 შემთხვევაშ�? endStr: // If end of string char მ�?აღწ�?ა,

 შემთხვევაშ�? newLine: // ან თუ end of line char მ�?აღწ�?ა,

 pChar = new char[theVector.ზომა() + 1];

 memset(pChar, 0, theVector.ზომა() + 1);



  for (int f = 0; f < theVector.ზომა(); ვ++)

 pChar[f] = theVector[f];

 დაბრუნება pChar;

შესვენება;

 default: // ნებ�?სმ�?ერ�? რეგულარულ�? char

theVector.push_back(ბუფერულ�?);

შესვენება;

}

}

}

არასამთავრობო ბლოკ�?რება და ას�?ნქრონულ�? სოკეტებ�?ს

სანამ ამ ეტაპზე ჩვენ უკვე ვსაუბრობთ დაბლოკვა სოკეტებ�?ს, სადაც მოუწოდებენ ფუნქც�?ა, როგორ�?ცაა მ�?�?ღოს() ელოდება განუსაზღვრელ�? ვად�?თ მომხმარებლ�?ს დაკავშ�?რება. არასამთავრობო დაბლოკვა socket ბრუნდება მაშ�?ნვე, როდესაც �?ს განუცხადა, რომ რამე, არც წარმატებულ�? შედეგ�?, შეცდომა, ან არაფერ�? (რაც მ�?უთ�?თებს, რომ არ �?ქნება რაღაც, რომ მ�?�?ღოთ შემდეგ). მ�?ნუს�? ეს ტ�?პ�? არ�?ს �?ს, რომ თქვენ უნდა ხელ�?თ შეკ�?თხვ�?ს სოკეტ�? თუ შედეგ�? დადგა ყოველ ფუნქც�?ა თქვენ დარეკეთ. თქვენ ვერ გა�?ვლ�?ს კომპლექტ�? სოკეტებ�?ს, რომ select() ფუნქც�?ა, თუ რომელ�? პ�?რობა არ�?ს მზად კ�?თხვა, წერა, ან დაბრუნდა შეცდომებ�?.

ფუნქც�?ებ�?ს გამოყენებ�?თ ას�?ნქრონულ�? სოკეტებ�?ს ასევე დაბრუნებას დაუყოვნებლ�?ვ, მაგრამ თქვენ შეგ�?ძლ�?ათ მ�?უთ�?თოთ წერ�?ლ�?ს გაგზავნას, თქვენ�? ფანჯრ�?ს პროცედურა, როდესაც გარკვეულ�? მოვლენა მოხდა. მაგალ�?თად, თქვენ შეგ�?ძლ�?ათ socket გამოგვ�?გზავნეთ SOCKET_GOTMSG გაგზავნა მაშ�?ნ, როდესაც �?ს �?ღებს რა�?მე. როგორც წეს�?, ეს ჭკვ�?ან�? შემოწმება შეცდომებ�? (რთულ�?, მაგრამ აუც�?ლებელ�?), როდესაც თქვენ მ�?�?ღებთ socket გაგზავნა, რათა თავ�?დან ა�?ც�?ლოს, რამაც ზედმეტ�? პრობლემებ�? მოგვ�?ანებ�?თ. პ�?რველ რ�?გშ�?, მოდ�?თ განვსაზღვროთ ზოგ�?ერთ�? ფუნქც�?ა ჩვენ ვ�?ყენებთ, რათა შე�?ქმნას ას�?ნქრონულ�? ბუდე:

  • int WSAAsyncSelect ( SOCKET s, HWND hwnd, unsigned int wMsg, ლევენთ )
    ეს ფუნქც�?ა გამო�?ყენება, რათა დადგ�?ნდეს socket როგორც ას�?ნქრონულ�? და ასოც�?რებულ�? გაგზავნა �?გ�?. s არ�?ს socket თქვენ მუშაობა. hwnd არ�?ს სახელურ�? ფანჯარა, რომელ�?ც მ�?�?ღებს გაგზავნა როდესაც ბუდე ქმნ�?ს ღონ�?სძ�?ება. wMsg არ�?ს გაგზავნა გსურთ გაუგზავნოთ თქვენ�? ფანჯარა პროცედურა (მაგალ�?თად, არ�?ს SOCKET_GOTMSG გაგზავნა ზემოთ). “ლევენთ პარამეტრ�? �?ღებს ერთ ან მეტ დროშებ�? რომ გ�?თხრათ, სოკეტ�?, რომელ�?ც მოვლენებ�?, გამოაგზავნოთ თქვენ�? შეტყობ�?ნება. ზოგ�?ერთ�? �?მ დროშებ�?:

    • FD_READ: Socket არ�?ს მზად, მ�?�?ღოს მონაცემებ�?
    • FD_WRITE: ბუდე მზად არ�?ს გააგზავნოს მონაცემებ�?
    • FD_ACCEPT: მეორად�? სერვერებ�?, ეს წერ�?ლ�? მ�?უთ�?თებს, მომხმარებელ�? უკავშ�?რდება
    • FD_CONNECT: გამო�?ყენება კლ�?ენტ�?ს პროგრამა, ეს მეს�?ჯ�? ეუბნება, სოკეტ�? აქვს უკავშ�?რდება
    • FD_CLOSE: socket ახლახანს და�?ხურა
  • WSAGETSELECTERROR ( LPARAM lparam )
    განსაზღვრავს, თუ socket დაბრუნდა შეცდომა. ტექნ�?კურად, ეს არ არ�?ს ფუნქც�?ა, მაგრამ მაკრო (თქვენ ნამდვ�?ლად გენერ�?რება smalltalk პარტ�?ებ�? ამ პატარა factoid).
  • WSAGETSELECTEVENT ( LPARAM lparam )
    კ�?დევ ერთ�? სასარგებლო მაკრო განსაზღვრულ�? winsock2.h არ�?ს WSAGETSELECTEVENT(), რომელ�?ც არ�?ს მეორად�?, რომ ნახოთ ზუსტად რა socket გააკეთა.

ასე რომ, მოდ�?თ, შე�?ქმნა ას�?ნქრონულ�? ბუდე:

// ჩვენ ვ�?წყებთ შექმნ�?თ დროშა რომ Windows გამო�?ყენებს, რათა დაგვ�?კავშ�?რდ�?თ, როდესაც რაღაც ხდება,

#განსაზღვრავს THERE_WAS_A_SOCKET_EVENT WM_USER + 100 // WM_USER არ�?ს ბაზა საბაჟო შეტყობ�?ნებებ�?

// სადღაც ჩვენ�? �?ნ�?ც�?ალ�?ზაც�?�?სას კოდ�? შემდეგ CreateWindow (), ჩვენ მოვუწოდებთ WSAAsyncSelect ()

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



// ეს �?თარგმნება: Windows, გთხოვთ, დამ�?კავშ�?რდეს THERE_WAS_A_SOCKET_EVENT დროშა, რომ მე

// წ�?ნასწარ განსაზღვრულ�? როდესაც არსებობს მონაცემებ�?, რომ წავ�?კ�?თხე (FD_READ), ან როდესაც მე ვარ, უფასო მონაცემებ�?ს

// (FD_WRITE), ან როდესაც მე წარმატებ�?თ დაკავშ�?რებულ�? ვ�?ნმე (FD_CONNECT), ან მაშ�?ნ, როდესაც ა.შ....

// ჩვენ�? ფანჯარა პროცედურა (ფუნქც�?ა, რომელ�?ც ამუშავებს ყველა შეტყობ�?ნებებ�?, რომ Windows აგზავნ�?ს თქვენ�? app)

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

{



 switch ( msg )

{

 შემთხვევაშ�? THERE_WAS_A_SOCKET_EVENT:

 თუ ( WSAGETSELECTERROR ( lParam ) )

 { // თუ შეცდომა მოხდა,

 closesocket ( theSocket );

 WSACleanup (); // გამორთვა Winsock

 დაბრუნება NETWORK_ERROR;

}

 switch ( WSAGETSELECTEVENT ( lParam ) )

 { // თუ რა მოხდა ზუსტად?

 შემთხვევაშ�? FD_READ:

 // მ�?ღება მონაცემებ�?

შესვენება;

 შემთხვევაშ�? FD_WRITE:

 // დაწერეთმონაცემებ�?

შესვენება;

 შემთხვევაშ�? FD_CONNECT:

 // უბრალოდ დაკავშ�?რებულ�? სერვერზე

შესვენება;

 შემთხვევაშ�? ... // �?გ�?ვე კონფ�?გურაც�?ა სხვა დროშებ�?

შესვენება;

}

შესვენება;



 // სხვა შემთხვევაშ�? განცხადებებ�? ლოგ�?კა, რომელ�?ც ამუშავებს სხვა Windows შეტყობ�?ნებებ�?



}

}

გა�?თვალ�?სწ�?ნეთ, რომ თქვენ ვერ განსაზღვრავს ერთ�? გაგზავნა თ�?თოეულ�? მოვლენა, როგორ�?ცაა SOCKET_GOTMSG �?ყ�?დება FD_READ და შემდეგ SOCKET_CONNECTED �?ყ�?დება FD_CONNECT. ეს �?მ�?ტომ, რომ განმეორებ�?თ�? ზარებ�? WSAAsyncSelect () კონფ�?გურაც�?ა თ�?თოეულ�? დროშა �?ქნება პასუხ�?ს ეფექტ�? ბოლო ზარ�? WSAAsyncSelect ().

უფრო გაკვეთ�?ლებ�? და ბმულებ�?

მე დავწერე ამ tutorial წლ�?ს დეკემბერშ�?, 2000, და შვ�?დ�? ან �?მდენად წლ�?ს შემდეგ არ მ�?ნახავს მუდმ�?ვ�? ნაკად�? ს�?ა და გაუმჯობესება. მე �?მედ�? მაქვს, რომ თქვენ სარგებლობდა კ�?თხულობს, როგორც მე სარგებლობდა წერა: გმადლობთ, რომ სარგებლობთ Johnnie �?ს Winsock Tutorial. ზემოთ არ�?ს, მაგრამ მოკლე მ�?მოხ�?ლვა შესაძლებლობებ�?, თქვენ შე�?ძლება მ�?აღწ�?ოს მეშვეობ�?თ Winsock და სხვებ�? არ გაკეთდა, ბევრად უკეთ, ვ�?დრე ჩემთვ�?ს საცდელ�? სპეც�?ფ�?კა ამ თემაზე:

(ამოძრავეთ თქვენ�? მაუს�?ს მეტ�? წ�?გნ�?ს ყდა მეტ�? �?ნფორმაც�?ა.)
– See more at: http://johnnie.jerrata.com/winsocktutorial/#sthash.IMglbIzP.dpuf

free kindergarten printable worksheet Consonant Digraph Worksheets For First Grade eftps direct payment worksheet long form Make Your Own Superhero Worksheet An Inconvenient Truth Worksheet Answers Chemical Nomenclature Worksheet Printable Math Worksheets For 3Rd Graders contemplation worksheets Whole Number Quadratic Equation Completing The Square Worksheet Adding Fractions With Unlike Denominators Worksheets 5Th Grade Worksheets Multiplication And Area Home |