Winsock Examples
Revision as of 10:50, 7 March 2008 by PeterHarding (talk | contribs) (New page: =Examples= ==Winsock 1== ===gethtttp.c=== <pre> // // GetHTTP.cpp // // Retrieves a file using the Hyper Text Transfer Protocol // and prints its contents to stdout. // // // Pass the ...)
Examples
Winsock 1
gethtttp.c
// // GetHTTP.cpp // // Retrieves a file using the Hyper Text Transfer Protocol // and prints its contents to stdout. // // // Pass the server name and full path of the file on the // command line and redirect the output to a file. The program // prints messages to stderr as it progresses. // // Example: // GetHTTP www.idgbooks.com /index.html > index.html // #include <stdio.h> #include <fcntl.h> #include <io.h> #include <winsock.h> void GetHTTP(LPCSTR lpServerName, LPCSTR lpFileName); // Helper macro for displaying errors #define PRINTERROR(s) \ fprintf(stderr,"\n%: %d\n", s, WSAGetLastError()) //////////////////////////////////////////////////////////// void main(int argc, char **argv) { WORD wVersionRequested = MAKEWORD(1,1); WSADATA wsaData; int nRet; // // Check arguments // if (argc != 3) { fprintf(stderr, "\nSyntax: GetHTTP ServerName FullPathName\n"); return; } // // Initialize WinSock.dll // nRet = WSAStartup(wVersionRequested, &wsaData); if (nRet) { fprintf(stderr,"\nWSAStartup(): %d\n", nRet); WSACleanup(); return; } // // Check WinSock version // if (wsaData.wVersion != wVersionRequested) { fprintf(stderr,"\nWinSock version not supported\n"); WSACleanup(); return; } // // Set "stdout" to binary mode // so that redirection will work // for .gif and .jpg files // _setmode(_fileno(stdout), _O_BINARY); // // Call GetHTTP() to do all the work // GetHTTP(argv[1], argv[2]); // // Release WinSock // WSACleanup(); } //////////////////////////////////////////////////////////// void GetHTTP(LPCSTR lpServerName, LPCSTR lpFileName) { // // Use inet_addr() to determine if we're dealing with a name // or an address // IN_ADDR iaHost; LPHOSTENT lpHostEntry; iaHost.s_addr = inet_addr(lpServerName); if (iaHost.s_addr == INADDR_NONE) { // Wasn't an IP address string, assume it is a name lpHostEntry = gethostbyname(lpServerName); } else { // It was a valid IP address string lpHostEntry = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr), AF_INET); } if (lpHostEntry == NULL) { PRINTERROR("gethostbyname()"); return; } // // Create a TCP/IP stream socket // SOCKET Socket; Socket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (Socket == INVALID_SOCKET) { PRINTERROR("socket()"); return; } // // Find the port number for the HTTP service on TCP // LPSERVENT lpServEnt; SOCKADDR_IN saServer; lpServEnt = getservbyname("http", "tcp"); if (lpServEnt == NULL) saServer.sin_port = htons(80); else saServer.sin_port = lpServEnt->s_port; // // Fill in the rest of the server address structure // saServer.sin_family = AF_INET; saServer.sin_addr = *((LPIN_ADDR)*lpHostEntry->h_addr_list); // // Connect the socket // int nRet; nRet = connect(Socket, (LPSOCKADDR)&saServer, sizeof(SOCKADDR_IN)); if (nRet == SOCKET_ERROR) { PRINTERROR("connect()"); closesocket(Socket); return; } // // Format the HTTP request // char szBuffer[1024]; sprintf(szBuffer, "GET %s\n", lpFileName); nRet = send(Socket, szBuffer, strlen(szBuffer), 0); if (nRet == SOCKET_ERROR) { PRINTERROR("send()"); closesocket(Socket); return; } // // Receive the file contents and print to stdout // while(1) { // Wait to receive, nRet = NumberOfBytesReceived nRet = recv(Socket, szBuffer, sizeof(szBuffer), 0); if (nRet == SOCKET_ERROR) { PRINTERROR("recv()"); break; } fprintf(stderr,"\nrecv() returned %d bytes", nRet); // Did the server close the connection? if (nRet == 0) break; // Write to stdout fwrite(szBuffer, nRet, 1, stdout); } closesocket(Socket); }
ping.c
// // PING.C -- Ping program using ICMP and RAW Sockets // #include <stdio.h> #include <stdlib.h> #include <winsock.h> #include "ping.h" // Internal Functions void Ping(LPCSTR pstrHost); void ReportError(LPCSTR pstrFrom); int WaitForEchoReply(SOCKET s); u_short in_cksum(u_short *addr, int len); // ICMP Echo Request/Reply functions int SendEchoRequest(SOCKET, LPSOCKADDR_IN); DWORD RecvEchoReply(SOCKET, LPSOCKADDR_IN, u_char *); // main() void main(int argc, char **argv) { WSADATA wsaData; WORD wVersionRequested = MAKEWORD(1,1); int nRet; // Check arguments if (argc != 2) { fprintf(stderr,"\nUsage: ping hostname\n"); return; } // Init WinSock nRet = WSAStartup(wVersionRequested, &wsaData); if (nRet) { fprintf(stderr,"\nError initializing WinSock\n"); return; } // Check version if (wsaData.wVersion != wVersionRequested) { fprintf(stderr,"\nWinSock version not supported\n"); return; } // Go do the ping Ping(argv[1]); // Free WinSock WSACleanup(); } // Ping() // Calls SendEchoRequest() and // RecvEchoReply() and prints results void Ping(LPCSTR pstrHost) { SOCKET rawSocket; LPHOSTENT lpHost; struct sockaddr_in saDest; struct sockaddr_in saSrc; DWORD dwTimeSent; DWORD dwElapsed; u_char cTTL; int nLoop; int nRet; // Create a Raw socket rawSocket = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP); if (rawSocket == SOCKET_ERROR) { ReportError("socket()"); return; } // Lookup host lpHost = gethostbyname(pstrHost); if (lpHost == NULL) { fprintf(stderr,"\nHost not found: %s\n", pstrHost); return; } // Setup destination socket address saDest.sin_addr.s_addr = *((u_long FAR *) (lpHost->h_addr)); saDest.sin_family = AF_INET; saDest.sin_port = 0; // Tell the user what we're doing printf("\nPinging %s [%s] with %d bytes of data:\n", pstrHost, inet_ntoa(saDest.sin_addr), REQ_DATASIZE); // Ping multiple times for (nLoop = 0; nLoop < 4; nLoop++) { // Send ICMP echo request SendEchoRequest(rawSocket, &saDest); // Use select() to wait for data to be received nRet = WaitForEchoReply(rawSocket); if (nRet == SOCKET_ERROR) { ReportError("select()"); break; } if (!nRet) { printf("\nTimeOut"); break; } // Receive reply dwTimeSent = RecvEchoReply(rawSocket, &saSrc, &cTTL); // Calculate elapsed time dwElapsed = GetTickCount() - dwTimeSent; printf("\nReply from: %s: bytes=%d time=%ldms TTL=%d", inet_ntoa(saSrc.sin_addr), REQ_DATASIZE, dwElapsed, cTTL); } printf("\n"); nRet = closesocket(rawSocket); if (nRet == SOCKET_ERROR) ReportError("closesocket()"); } // SendEchoRequest() // Fill in echo request header // and send to destination int SendEchoRequest(SOCKET s,LPSOCKADDR_IN lpstToAddr) { static ECHOREQUEST echoReq; static nId = 1; static nSeq = 1; int nRet; // Fill in echo request echoReq.icmpHdr.Type = ICMP_ECHOREQ; echoReq.icmpHdr.Code = 0; echoReq.icmpHdr.Checksum = 0; echoReq.icmpHdr.ID = nId++; echoReq.icmpHdr.Seq = nSeq++; // Fill in some data to send for (nRet = 0; nRet < REQ_DATASIZE; nRet++) echoReq.cData[nRet] = ' '+nRet; // Save tick count when sent echoReq.dwTime = GetTickCount(); // Put data in packet and compute checksum echoReq.icmpHdr.Checksum = in_cksum((u_short *)&echoReq, sizeof(ECHOREQUEST)); // Send the echo request nRet = sendto(s, /* socket */ (LPSTR)&echoReq, /* buffer */ sizeof(ECHOREQUEST), 0, /* flags */ (LPSOCKADDR)lpstToAddr, /* destination */ sizeof(SOCKADDR_IN)); /* address length */ if (nRet == SOCKET_ERROR) ReportError("sendto()"); return (nRet); } // RecvEchoReply() // Receive incoming data // and parse out fields DWORD RecvEchoReply(SOCKET s, LPSOCKADDR_IN lpsaFrom, u_char *pTTL) { ECHOREPLY echoReply; int nRet; int nAddrLen = sizeof(struct sockaddr_in); // Receive the echo reply nRet = recvfrom(s, // socket (LPSTR)&echoReply, // buffer sizeof(ECHOREPLY), // size of buffer 0, // flags (LPSOCKADDR)lpsaFrom, // From address &nAddrLen); // pointer to address len // Check return value if (nRet == SOCKET_ERROR) ReportError("recvfrom()"); // return time sent and IP TTL *pTTL = echoReply.ipHdr.TTL; return(echoReply.echoRequest.dwTime); } // What happened? void ReportError(LPCSTR pWhere) { fprintf(stderr,"\n%s error: %d\n", WSAGetLastError()); } // WaitForEchoReply() // Use select() to determine when // data is waiting to be read int WaitForEchoReply(SOCKET s) { struct timeval Timeout; fd_set readfds; readfds.fd_count = 1; readfds.fd_array[0] = s; Timeout.tv_sec = 5; Timeout.tv_usec = 0; return(select(1, &readfds, NULL, NULL, &Timeout)); } // // Mike Muuss' in_cksum() function // and his comments from the original // ping program // // * Author - // * Mike Muuss // * U. S. Army Ballistic Research Laboratory // * December, 1983 /* * I N _ C K S U M * * Checksum routine for Internet Protocol family headers (C Version) * */ u_short in_cksum(u_short *addr, int len) { register int nleft = len; register u_short *w = addr; register u_short answer; register int sum = 0; /* * Our algorithm is simple, using a 32 bit accumulator (sum), * we add sequential 16 bit words to it, and at the end, fold * back all the carry bits from the top 16 bits into the lower * 16 bits. */ while( nleft > 1 ) { sum += *w++; nleft -= 2; } /* mop up an odd byte, if necessary */ if( nleft == 1 ) { u_short u = 0; *(u_char *)(&u) = *(u_char *)w ; sum += u; } /* * add back carry outs from top 16 bits to low 16 bits */ sum = (sum >> 16) + (sum & 0xffff); /* add hi 16 to low 16 */ sum += (sum >> 16); /* add carry */ answer = ~sum; /* truncate to 16 bits */ return (answer); }