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

Home |