This article is coming from the Internet, the source is unknown! /// Say Winsock, there may be many people still don't know much, but I said OICQ, ICQ, Foxmail, Netants, Cuteftp, and the famous BO2K, etc., everyone should be very familiar. Nowadays, it is a network era. These network-based software is really red fire! How have you ever thought about how these software wrote? This is the content you want to introduce this article: Socket programming!
Socket (Chinese translation: socket) initially appeared on UNIX and quickly became one of the most popular network programming interfaces on UNIX. Later, Microsoft introduced it into Windows and achieved it, so starting from Windows 95, WinNT4, the system has built-in Winsock1.1, and later to Windows 98, Windows2000, its built-in Winsock DLL update to Winsock 2.2. Winsock1.1 has 2 I / O methods, 2 I / O models, to Winsock2.2, has two I / O methods, 5 I / O models. In addition, Winsock2.2 has many expansion and improvements in Socket, including name resolution, asynchronous processing, and more. These are very useful, but it is more complicated. If you want to be clear in just a short article, this article is just to open your head, as the saying goes: Everything is difficult! In fact, Winsock programming is very standardized. However, it is worth noting that it is difficult to grasp because it is programmed by the network, and sometimes you find that the program does not have expected results, but it is very difficult to try out where there is a problem!
Here, you will introduce you to the basic Socket client function and give a simple multi-threaded port scanner source code!
Let's talk about the basic programming steps:
1. Because Winsock currently has two versions: 2.2 and 1.1, we must first determine the Winsock version supported by the system! This will rely on the WSAStartup function! There is also a WSACLEANUP function! These two functions are Winsock programming must be called, where the function of the WSAStartup function is to initialize the Winsock DLL, because under Windows, Socket is implemented in a DLL. 1.1 version of the DLL is Winsock.dll, and 2.2 version of the DLL is WSOCK32.DLL, where in the 2.2 version of the system, the call to the WSOCK1.1 function is automatically mapped to Winsock.dll. The function of the WSAStartup function is to initialize the DLL, its function prototype is:
INT WSASTARTUP (Word WversionRequested, LPWSADATA LPWSADATA);
The first parameter is the Winsock version you want! Low byte is the main version, high byte is a deputy version! Since Winsock has two versions: 1.1 and 2.2, this parameter can be 0x101 or 0x202; the second parameter is a WSADATA structure for receiving the return information of the function! The WSAStartup function call success will return 0, otherwise returns a non-0 value!
Sample code:
Wsadata wsadata;
IF (WSAStartup (0x101, & WSADATA))
{
// Error handling!
}
Here is a list of external questions. Due to Win 95, Win NT4 comes with Winsock is a 1.1 version, so if your program is WINSOCK2.2, it is likely to run on it! Therefore, if you want you to write by the procedure supported by all Windows platform, it is best to declare it into version 1.1, but this will not be able to use a lot of Winsock2.2 talent! As for WSacleanup, it is easy to use "wsacleanup ();" In addition, one counter is maintained inside the DLL, only the first time calling WSAStartup is really loaded with the DLL, and the future call is just a simple addition counter, and the function of the WSACLEANup function is just the opposite, each call reduces the counter minus the counter, when the counter minus the counter At 0, the DLL is uninstalled from memory! Therefore, how many times, WSASTARTUP you call, should call the corresponding WSACleanup. 2. Create a socket
Creating a socket has two functions, socket and wsasocket, the former is a standard socket function, while the latter is Microsoft's extended function for Socket. The Socket function has 3 parameters, the first is the area that specifies the occurrence of communication, with AF_UNIX, AF_INET, AF_NS, etc. under Unix, and only AF_Inet is supported under Winsock1.1, and 2.2 adds AF_IRDA (infrared communication), AF_ATM (Asynchronous Network Communication), AF_NS, AF_IPX, etc .; the second parameter is the type of socket, in the AF_INET address family, there is SOCK_STREAM, SOCK_DGRAM, SOCK_RAW three socket types. Sock_stream is also the usual TCP, and SOCK_DGRAM is usually the UDP, and SOCK_RAW is used to provide some lower level control; the third parameter depends on the second parameter for specifying the socket The specific protocol used by the word is set to 0 means using the default protocol. The Socket function call successfully returns a socket descriptor, and the error returns Socket_ERROR.
Sample code:
Socket SK;
SK = Socket (AF_INET, SOCK_STREAM, 0);
IF (SK == Socket_ERROR)
{
// Error handling
}
3. Connect the server
After successfully invoking the socket function, the client is established with the server side. Similarly, establish a connection requires two functions: Connect and WSaconnect. The former is the standard socket function, the latter is Microsoft's extension function. The Connect function has 3 parameters, and the first is the socket descriptor used. The second parameter is a SockAddr structure. The SockAddr structure is a universal structure, which simply defines a byte array, TCP / IP is generally explained as a SockAddr_in structure, and the third parameter is the length of the structure, which is generally obtained by the SizeOf function. Connect function call failed, return to Socket_ERROR! Bamboo
Sample code:
SockAddr_in sock;
Sock.sin_family = AF_INET;
Sock.sin_port = HTONS (80);
Sock.sin_addr.s_addr = inet_addr ("202.205.210.1");
IF (Connect (SK, (SockAddr *) & Sock, Sizeof (SOCK) == Socket_ERROR)
{
// Error handling
}
One point here is to indicate that the value for filling out the SockAddr_in structure must be a value represented in the network byte order, and the value of the unit byte sequence cannot be directly used. The reason for this is because there are different systems on the network, and the sequence of the byte arrangement used in different systems is different. Some are the pre-word, the low words are after, and some are just the opposite. In order to unify, a so-called network byte order is specified. The HTONL function can convert the local Unsigned long data into network byte sequence. HTons is data that converts the data of the Unsigned Short into network byte sequence. The functionality of NTOHS and NTOHL is just the opposite. In addition, the SIN_ADDR.s_ADDR member of the SockAddr_in structure is used to describe a value of the other party address, the internet address value, and the actual application, most of us is the IP address or domain name, such as 202.210.205.1 or www.cfan.cn .NET, can convert the IP address representing the point-assigned IP address to the required value with the inet_addr function, and the information of the host represented by the easy-to-use name can be retrieved by gethostByName, WSaAsyngetByname. The gethostByname function call success will return a Hostent structure pointer. If the error is returned back. Here is the usage of the gethostbyname function. Hostent * host;
.......
Host = gethostbyname ("www.cfan.cn.net")
IF (Host == Null)
{
// Error handling
SOCK.SIN_ADDR.S_ADDR = * ((unsigned long *) Host → h_addr_list [0]);
......
4. Send and receive data
Since it is established here, the functions that can be used have Send and WSasend, and the reception can use RECV and WSARECV. Similarly, the full-write function is a standard Socket function, and the WSA is starting with Microsoft's extended function. The Send function has 4 parameters: the first is the socket descriptor used by the transmission operation, the second is the address of the data buffer to be transmitted, as a char * type, as for other types of data, can be converted with a mandatory type ( Char *). Re-converted back in the receiving end! The third parameter is the size of the buffer sent, that is, the number of bytes to be sent! The fourth parameter is an additional sign, which can be 0, msg_oob, msg_dontroute, the user who is familiar with the computer should be unfamiliar with Oob, because Win95 has a very famous system vulnerability is the so-called "OOB error", one is accidentally The system crashes (Win98 has an ICMP error, with the socket type of Sock_RAW type involves ICMP!). If there is no special requirements for the transmitted data, set directly to 0. The parameters of the RECV function are also 4 its meaning and the Send function. It is only its second parameter to point to the address of the buffer for receiving data. Send, the RECV call successfully returns the number of bytes sent or received, returns socket_error! if the call failed
Sample code (SEND function):
Socket SK;
Char sztest [] = "this is an example!"
INT IRET;
... (here you omitly create a socket, connect ...)
IRET = Send (SK, SzTest, Strlen (SzTest), 0);
IF (IRET == Socket_ERROR)
{
// Error handling
}
Else IF (IRET! = Strlen (sztest))
MessageBox (NULL, "No All Data", "Warning", MB_OK;
Sample code (RECV function)
Socket SK; char sztest [20]
INT IRET;
... (here you omitly create a socket, connection ...)
Iret = RECV (SK, SzTest, 20, 0);
IF (IRET == Socket_ERROR)
{
// Error handling
}
Sztest [IRet] = `/ 0`; // This line of code is indispensable! Because the RECV function does not automatically set the data buffer to the end of the data ended (`/ 0`), there will be a buffer offline in one without paying attention. Of course, you can also clear the buffer 0 (zeromeMEMORY or MEMSET) before calling the RECV function, but it is recommended to add this sentence.
5. Disconnect connection
Use CloseSocket.closeSocket (SK); additionally, you can also use Shutdown to turn off the socket, which provides more option control, due to space limit, here is no longer in-depth!
In this way, the basic (basic) content of the client is finished! The following youn get the source code for a simple multi-threaded port scanner (Warning: Use the port scanner to scan the computer with the port scanner and implement port attacks for others).
This is a typical TCP port scanner that determines whether the port on the server is open by trying to connect the server with the CONNECT function. This scanner is multi-threaded, and now the Winsock programming mostly adopts multi-threaded technology, so you can make full use of bandwidth, such as 5 ant downloads of Netants, some FTP software multi-thread upload, etc! In order to enhance the readability of the code, I didn't add badly to handle!
// Source Code In C Builder5
#include
#pragma HDRSTOP
#include "unit1.h"
#include
#include
#define threadnum 10 // Thread number
#define mutexname "Welcome to lovebcb.yeah.net"
#pragma package (smart_init)
#pragma resource "* .dfm"
Typedef struct g_scan // This is a custom structure
{
Char Szfile [40]; // File name for storage results
Char Szmutex [40]; // Used to store the name of the mutual exclusion, this is a method of multi-thread guarantee thread security
Unsigned short sport; // Scan start port, native byte order
UNSIGNED SHORT Eport; // Termination port, native byte order
Unsigned long goali; // Target host IP, network byte order
Int result; // for storage results
} * Pg_scan;
TFORLOVER * forLover; // This is the form
Handle hthread [threadnum];
g_scan gscan [threadnum];
DWORD DWTHREADID, DWTHREADCODE;
UNSIGNED short uspart; // Used to split the number of ports to be scanned, assign each thread
UNSigned long ulip;
INT iLiveThread; // Used to store the number of threads
Unsigned long serverip (char * serverip);
DWORD WINAPI Scanport (LPVOID LP)
/ * This is the main thread function scanport * /
DWORD WINAPI Scanport (LPVOID LP)
{
PG_scan pgscan = (pg_scan) lp;
Char SzResult [40];
SockAddr_in Sock; unsigned short noport = pgscan → Sport-1; // Used to store the current scanned port number
FILE * fp; // file pointer
Handle Hmutex = OpenMuteX (Mutex_all_Access, False, Pgscan → Szmutex);
Socket SK = Socket (AF_INET, SOCK_STREAM, 0);
Sock.sin_family = AF_INET;
Sock.sin_addr.s_addr = pgscan → Goalip;
WHILE
{
Sock.sin_port = HTONS ( NOWPORT)
IF (Connect (SK, (SockAddr *) & Sock, SIZEOF (SOCK)) == Socket_ERROR)
CONTINUE;
/ * Since it is used here, it is generally impossible to connect to Socket_ERROR, so that the cycle is ended with CONTINUE, that is, restart a cycle. If the return value is not socket_error, it means the connection is successful, that is, the target host is open. * /
WSPRINTF (SzResult, "Target Host:% s Port:% D Open / RPORT_NTOA (Sock.SIN_ADDR), NOWPORT); WaitForsingleObject (hmutex, infinite);
/ * With WaitForsinleObject to ensure that thread security Infinite is waiting until the mutex has signal * /
FP = fopen (pgscan → szfile, "a");
Fwrite (SzResult, Sizeof (Char), Strlen (SzResult), FP);
Fclose (fp);
Pgscan → Result ;
ReleaseMutex (hmutex); // Release the mutex
CloseSocket (SK); // Since connection has been established, you have to turn off the connection here.
SK = Socket (AF_INET, SOCK_STREAM, 0); // Re-create a socket
}