Use VC ++ for WinSock programming -- Client

Source: Internet
Author: User
Tags htons
When talking about WinSock, many people may not know much about it yet, but they should be familiar with OICQ, ICQ, Foxmail, NetAnts, CuteFTP, and well-known bo2k. Today is the Internet era, and these network-based software is booming! Have you ever wondered how the software was written? This is what this article will introduce: socket programming!

Socket (Chinese Translation: socket) first appeared on UNIX and soon became one of the most popular network programming interfaces on UNIX. Later, Microsoft introduced it into windows and implemented it. So from Windows 95 and winnt4, the system built in winsock1.1, and then to Windows 98 and windows, its built-in Winsock DLL is updated to winsock2.2. Winsock1.1 has two I/O modes and two I/O models. When it reaches winsock2.2, two I/O modes and five I/O models are available. In addition, winsock2.2 has expanded and improved the socket, including name parsing and asynchronous processing. These are all very useful content, but they are also complicated. It is impossible to make it clear in a short article. The purpose of this article is just to start for you. As the saying goes: Everything is difficult! In fact, WinSock programming is a routine formula. However, it is worth noting that sometimes it is difficult to grasp, because it is programmed on a network, and sometimes you find that the running program cannot get the expected results, however, it is difficult to debug what went wrong!

The following describes the basic Socket Client functions and provides the source code of a simple multi-threaded port scanner!

First, 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 depends on the wsastartup function! There is also a wsacleanup function! These two functions must be called in WinSock programming. The wsastartup function initializes Winsock DLL, because in windows, socket is implemented in the form of DLL. The DLL of Version 1.1 is Winsock. DLL, while the DLL of Version 2.2 is wsock32.dll. In the system of Version 2.2, the call to the winsock1.1 function is automatically mapped to Winsock by wsock32.dll. DLL. The function of the wsastartup function is to initialize the DLL. Its prototype is:

Int wsastartup (word wversionrequested, lpwsadata );

The first parameter is the required Winsock version! The primary version is low, and the secondary version is high! Currently, Winsock has two versions: 1.1 and 2.2. Therefore, this parameter can be 0x101 or 0x202. The second parameter is a wsadata structure used to receive information returned by the function! If the wsastartup function is successfully called, 0 is returned. Otherwise, a non-0 value is returned!

Sample Code:

Wsadata;

If (wsastartup (0x101, & wsadata ))

{

// Handle the error!

}

Here is an aside. Since Windows 95 and Windows NT4 come with Winsock 1.1, if your program is based on winsock2.2, it may not be able to run on it! Therefore, if you want your program to be supported by all Windows platforms, it is best to declare it as Version 1.1, but this will not be able to use many features available in winsock2.2! Wsacleanup is easy to use. Just use "wsacleanup! In addition, there is a counter in the DLL. Only the first time wsastartup is called, The dll will be loaded. In the future, the counter will be added, while the wsacleanup function will have the opposite function, every call reduces the counter by 1. When the counter is reduced to 0, the DLL will be detached from the memory! Therefore, the number of wsastartup calls is the number of wsacleanup calls.

2. Create a socket

There are two functions for creating a socket: socket and wsasocket. The former is a standard socket function, and the latter is Microsoft's socket extension function. The socket function has three parameters. The first parameter is the region where the communication occurs. af_unix, af_inet, and af_ns are used in Unix. In winsock1.1, only af_inet is supported, af_irda (infrared communication), af_atm (Asynchronous Network Communication), af_ns, and af_ipx are added to 2.2. The 2nd parameters are socket types. In the af_inet address family, there are three socket types: sock_stream, sock_dgram, and sock_raw. Sock_stream is also known as TCP, while sock_dgram is usually called UDP, while sock_raw is used to provide some lower-level control. 3rd parameters depend on 2nd parameters, specifies the specific protocol used by the socket. If it is set to 0, the default protocol is used. If the socket function is successfully called, a socket descriptor is returned. If an error occurs, socket_error is returned.

Sample Code:

Socket SK;

SK = socket (af_inet, sock_stream, 0 );

If (Sk = socket_error)

{

// Handle errors

}

3. Connect to the server

After the socket function is successfully called, the client establishes a connection with the server. Similarly, two functions are required to establish a connection: connect and wsaconnect. The former is a standard socket function, and the latter is a Microsoft Extension function. The connect function has three parameters, 1st are the socket descriptor used for the connection, 2nd are a sockaddr structure, and the sockaddr structure is a general structure, it simply defines a byte array. Under TCP/IP, it is generally interpreted as the sockaddr_in structure. The length of the structure is the 3rd parameters, which are generally obtained using the sizeof function. If the connect function fails to be called, socket_error is returned!

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)

{

// Handle errors

}

Here, we need to note that the value used to fill in the sockaddr_in structure must be expressed in the byte sequence of the network, rather than directly using the value in the byte sequence of the local machine. The reason for this rule is that there are different systems on the network, and the data storage in different systems adopts different byte order, some of which are the top and the bottom, some are the opposite. A so-called network byte sequence is defined for unification. The htonl function can convert the local unsigned long data into bytes of the network. Htons converts unsigned short data to bytes in the network. The functions of ntohs and ntohl are the opposite. In addition, the sin_addr.s_addr member in the sockaddr_in structure is required to describe the value of the Peer address, that is, the internet address value. In actual applications, most of the information we get is the IP address or domain name, such as 202.210.205.1 or www, you can use the inet_addr function to convert the IP address represented by the dot method to the required value. You can use gethostbyname and wsaasyngethostbyname to retrieve the host information represented by an easy-to-use name. If the gethostbyname function is successfully called, a pointer to the hostent structure is returned. If an error occurs, null is returned. The following describes how to use the gethostbyname function.

Hostent * Host;

.......

Host = gethostbyname ("www.cfan.cn.net ")

If (host = NULL)

{

// Handle errors

Sock. sin_addr.s_addr = * (unsigned long *) host → h_addr_list [0]);

......

4. send and receive data

Because the sock_stream type connection is established here, the send function can use SEND and wsasend, And the receive function can use Recv and wsarecv. Similarly, all lower-case functions are standard socket functions. The send function starting with WSA has four parameters: the first is the socket descriptor used for sending operations, the second is the address of the data buffer to be sent, Which is char * type. For other types of data, you can use forced type conversion (char *). Use forced type conversion at the receiving end to convert it back! The second parameter indicates the size of the buffer to be sent, that is, the number of bytes to be sent! The third parameter is an additional identifier, which can be 0, MSG_OOB, or msg_dontroute. Users familiar with computers should be familiar with OOB, one of the most famous system vulnerabilities in Win95 is the so-called "OOB error". When you accidentally crash the system (Win98 has an ICMP error, using a socket of the sock_raw type will involve ICMP !). If you do not have special requirements for the sent data, set it to 0 directly. The parameters of the Recv function are similar to those of the send function. The second parameter points to the address of the buffer used to receive data. The number of sent or received bytes is returned if the send or Recv call is successful. If the call fails, socket_error is returned!

Sample Code (send function ):

Socket SK;

Char sztest [] = "this is an example !"

Int iret;

...... (Create socket, connect ...)

Iret = Send (SK, sztest, strlen (sztest), 0 );

If (iret = socket_error)

{

// Handle errors

}

Else if (iret! = Strlen (sztest ))

MessageBox (null, "not send all data", "warning", mb_ OK );

Sample Code (Recv function)

Socket SK;

Char sztest [20]

Int iret;

...... (Create socket is omitted here to connect ......)

Iret = Recv (SK, sztest, 20, 0 );

If (iret = socket_error)

{

// Handle errors

}

Sztest [iret] = '/0'; // This line of code is indispensable! Because the Recv function does not automatically set the end of the data buffer as the air stop sign ('/0') indicating the end Of the data buffer, the buffer will be out of bounds once you leave it alone. Of course, you can also clear the buffer to 0 (using zeromemory or memset) before calling the Recv function. However, we recommend that you add this sentence.

5. Disconnect

Use closesocket. closesocket (SK). In addition, you can also use shutdown to close the socket, which provides more option control. Due to space limitations, we will not go into depth here!

In this way, the basic (basic) content of the client is finished! The following code provides a simple multi-threaded port scanner (warning: it is illegal to use a port scanner to scan others' computers and conduct port attacks on others' computers without permission ).

This is a typical TCP port scanner. It uses the connect function to connect the server to determine whether the port on the server is open. This scanner is multi-threaded. Currently, most WinSock programming adopts multi-threaded technology, which can make full use of bandwidth, such as downloading of five ant NetAnts and multi‑thread uploading of some FTP software! To enhance code readability, I did not add error handling!

// Source code in C ++ builder5

# Include

# Pragma hdrstop

# Include "unit1.h"

# Include

# Include

# Define threadnum 10 // Number of threads

# 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 used to store the result

Char szmutex [40]; // used to store the name of the mutex. This is a thread-safe method for multithreading.

Unsigned short sport; // The starting port for scanning, In the byte sequence of the local machine.

Unsigned short eport; // The termination port of the scan, In the byte sequence of the local machine.

Unsigned long goali; // the IP address of the target host, in bytes.

Int result; // used to store the result

} * Pg_scan;

Tforlover * forlover; // This is the form

Handle hthread [threadnum];

G_scan gscan [threadnum];

DWORD dwthreadid, dwthreadcode;

Unsigned short uspart; // used to separate the number of ports to be scanned and allocate them to each thread.

Unsigned long ulip;

Int ilivethread; // Number of threads used to store the activity

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 nowport = pgscan → sport-1; // The port number used to store the current scan.

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 (nowport

{

Sock. sin_port = htons (++ nowport)

If (connect (SK, (sockaddr *) & sock, sizeof (sock) = socket_error)

Continue;

/* Because the socket in blocking mode is used here, returning socket_error usually means that the connection fails. Therefore, use continue to end the loop, that is, start a loop again. If the returned value is not socket_error, the connection is successful, that is, the port is opened on the target host */

Wsprintf (szresult, "Target Host: % sport: % d Open/R/N", inet_ntoa (sock. sin_addr), nowport); waitforsingleobject (hmutex, infinite );

/* Use waitforsinleobject to ensure thread security. Infinite indicates waiting until the mutex has a signal */

Fp = fopen (pgscan → szfile, "");

Fwrite (szresult, sizeof (char), strlen (szresult), FP );

Fclose (FP );

Pgscan → result ++;

Releasemutex (hmutex); // release the mutex

Closesocket (SK); // close the connection because a connection has been established.

SK = socket (af_inet, sock_stream, 0); // recreate a socket

}

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.