1 / 23

Winsock Programming

Winsock Programming. Blocking and Asynchronous Sockets for Windows. History. MS-DOS/Windows not designed for networking Early Microsoft operating systems ignored the TCP/IP stack “Visionary” Bill Gates supports NETBIOS over TCP/IP Several packages offered by 3 rd parties

lester
Download Presentation

Winsock Programming

An Image/Link below is provided (as is) to download presentation Download Policy: Content on the Website is provided to you AS IS for your information and personal use and may not be sold / licensed / shared on other websites without getting consent from its author. Content is provided to you AS IS for your information and personal use only. Download presentation by click this link. While downloading, if for some reason you are not able to download a presentation, the publisher may have deleted the file from their server. During download, if you can't get a presentation, the file might be deleted by the publisher.

E N D

Presentation Transcript


  1. Winsock Programming Blocking and Asynchronous Sockets for Windows

  2. History • MS-DOS/Windows not designed for networking • Early Microsoft operating systems ignored the TCP/IP stack • “Visionary” Bill Gates supports NETBIOS over TCP/IP • Several packages offered by 3rd parties • “Trumpet Winsock” • None work particularly well

  3. What is Winsock? • API, SPI and ABI • API for application developers • SPI for network software vendors • ABI to ensure consistent interoperability between applications and various implementations of Winsock • Less important now that Microsoft has released a quality Winsock • No significant alternatives

  4. The API • Based on BSD sockets API • First of many Microsoft “hacks” • Complications due to differences between Unix and Windows • errno (Unix) vs. WSAGetLastError() • BSD sockets based on C and Unix • fork() • File descriptors

  5. Example: The Unix Way while (1) { newsockfd = accept(sockfd, (struct sockaddr *) &cli_addr, &clilen); if (newsockfd < 0) error("ERROR on accept"); pid = fork(); if (pid < 0) error("ERROR on fork"); if (pid == 0) { close(sockfd); dostuff(newsockfd); exit(0); } else close(newsockfd); }

  6. Steps to a Listen Socket • Initialize Winsock • Fill out SOCKADDR_IN (define the socket) • Create the socket • bind() the socket • Make the socket listen() • Wait on accept() • Handle clients via socket returned by accept()

  7. Example: Listening (simplified) // INITIALIZE sockVersion = MAKEWORD(1, 1); // Winsock version 1.1 WSAStartup(sockVersion, &wsaData); // CREATE SOCKET SOCKET listeningSocket; listeningSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // DEFINE SOCKET SOCKADDR_IN serverInfo; serverInfo.sin_family = AF_INET; serverInfo.sin_addr.s_addr = INADDR_ANY; serverInfo.sin_port = htons(8888); // BIND bind(listeningSocket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr)); // LISTEN listen(listeningSocket, 10); // ACCEPT SOCKET theClient; theClient = accept(listeningSocket, NULL, NULL);

  8. Steps to Connecting • Initialize Winsock • Fill out HOSTENT • Create socket • Fill out SOCKADDR_IN • Connect • Send/recv

  9. Example: Connecting (simplified) // INITIALIZE sockVersion = MAKEWORD(1, 1); WSAStartup(sockVersion, &wsaData); // FILL OUT HOSTENT LPHOSTENT hostEntry = gethostbyname("www.hal-pc.org"); // CREATE SOCKET SOCKET theSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); // FILL OUT SOCKADDR_IN SOCKADDR_IN serverInfo; serverInfo.sin_family = AF_INET; serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list); serverInfo.sin_port = htons(80); // CONNECT connect(theSocket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));

  10. Sending and Receiving • int send(SOCKET s, char * buf, int len, int flags); • Returns number of bytes sent or SOCKET_ERROR • int recv(SOCKET s, char * buf, int len, int flags); • Returns number of bytes received or SOCKET_ERROR • Send and recv must be done in loops to ensure all data is sent/received

  11. Problem: blocking • Many of these functions “block” • accept() • connect() • send() • recv() • One solution: poll sockets using select() • Another solution: threads • Coolest solution: asynchronous sockets

  12. Why Asynchronous? • Windows handles polling for you • Familiar Windows message paradigm • Easy to read code

  13. Why NOT Asynchronous? • Non-portable • Microsoft is evil • Use them anyways, they are cool

  14. Windows Messages • Message queue • Message pump • “first chance” message handling • Message Handler • Callback function

  15. Sample Message Pump HRESULT hRet; UINT Msg; while( (hRet = GetMessage( &Msg, NULL, 0, 0 )) != 0) {    if (hRet == -1) {       PostQuitMessage(1);    }    else    {       TranslateMessage(&Msg);       DispatchMessage(&Msg);    } }

  16. Sample Message Handler LRESULT CALLBACK WinProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) { switch(uMsg) { case WM_DESTROY: PostQuitMessage(WM_QUIT); break; default: return FALSE; } return TRUE; }

  17. How Does This Apply? • Windows sends messages when sockets are waiting • No need to poll • No need for many threads • Create sockets and go about other tasks • Handle sockets just like any other Windows control

  18. Making a socket asynchronous int PASCAL WSAAsyncSelect( SOCKET s, HWND hwnd, unsigned int Msg, long event ); Simple call to WSAAsyncSelect:

  19. Message and Events • Five events: • FD_READ • FD_WRITE • FD_CONNECT • FD_ACCEPT • FD_CLOSE • OR these together to tell Windows what notifications you need • User defined messages • WM_USER + n

  20. Handling the message • wParam: • socket instance • lParam: • HIWORD: • 0 (success) • Error code • LOWORD: • FD_READ, FD_WRITE, etc.

  21. Example: Handling FD_ACCEPT SOCKET s; switch (msg) { case WM_USER + 5: switch(WSAGETSELECTEVENT(lParam) { case FD_ACCEPT: s = accept(wParam, NULL, NULL); break; } break; }

  22. Summary • Why this is important: • Current Winsock responsible for increase in quantity and popularity of Internet applications • Almost all applications use the Internet somehow, or could be improved by using the Internet

  23. Example: Version Checking DWORD WINAPI CGlowdotChatServer::DoVersionCheckThreadProc(LPVOID pvoid) { struct sockaddr_in sa; struct hostent *hp; hp = gethostbyname(“www.stromcode.com”); memset(&sa,0,sizeof(sa)); // set address and port memcpy((char *)&sa.sin_addr, hp->h_addr, hp->h_length); sa.sin_family = hp->h_addrtype; sa.sin_port = htons((u_short)VERSION_CHECK_PORT); // create socket SOCKET s = socket(hp->h_addrtype, SOCK_STREAM, 0); std::string request ("GET /glowdotchat/server/checkversion.php?getcurrentversion=yes HTTP/1.1\nUser-Agent:Mozilla\nHost:www.stromcode.com\n\n"); send(s, request.c_str(), request.length(),0); char buf[1000]; std::string response(""); recv(s, buf, 1000, 0); response += std::string(buf); std::string::size_type pos1 = response.find(std::string("<current-version>")); std::string::size_type pos2 = response.find(std::string("</current-version>")); response = response.substr(pos1 + 17, pos2 - pos1 - 17); if (response == std::string(VERSION)) { // server up to date } else { // new version available } return 0; }

More Related