SoFunction
Updated on 2025-04-12

WinSock study notes in C language


6. Socket connection: Connect two sockets to prepare for communication. (Client)

int connect(SOCKET s, const struct sockaddr FAR * name, int namelen ) 

s is the created socket to be linked.

name is the socket address to be connected to.

namelen is the length of the structure of the socket address.

usage:

sockaddr_in addr; 
addr. sin_family=AF_INET; 
addr. sin_port=htons(0); //Ensure byte orderaddr. sin_addr.s_addr= htonl(INADDR_ANY) //Ensure byte orderint nResult=connect(s,(sockaddr*)&addr,sizeof(sockaddr)); 
if(nResult==SOCKET_ERROR) 
{ 
//Error handling} 

7. Socket sends data: (server side and client side)

int send(SOCKET s, const char FAR * buf, int len, int flags ) 
sSockets for server-side listening。 

buf is a pointer to the buffer to be sent.

len is the length of the sending data buffer.

flags sends a tag for data.

The return value is the number of characters to which the data is sent.

◆ Let’s talk about this sending mark here, and the same is true for the receiving mark discussed in the following 8:

The flag value must be 0 or a combination defined as follows: 0 means there is no special behavior.

#define MSG_OOB 0x1 /* process out-of-band data */ 
#define MSG_PEEK 0x2 /* peek at incoming message */ 
#define MSG_DONTROUTE 0x4 /* send without using routing tables */ 

MSG_OOB means that data should be sent out of band, and the so-called out-of-band data is TCP emergency data.
MSG_PEEK means to copy useful data into the buffer, but not delete it from the system buffer.
MSG_DONTROUTE means do not route packets.

usage:

char buf[]="xiaojin"; 
int nResult=send(s,buf,strlen(buf)); 
if(nResult==SOCKET_ERROR) 
{ 
//Error handling} 

8. Socket data reception: (client)

int recv( SOCKET s, char FAR * buf, int len, int flags ) 

s is a socket that prepares to receive data.

buf is a buffer to prepare for receiving data.

len is the size of the buffer to prepare for receiving data.

flags are data receiving tags.

Returns the number of characters of the received data.

usage:

char mess[1000]; 
int nResult =recv(s,mess,1000,0); 
if(nResult==SOCKET_ERROR) 
{ 
//Error handling} 

9. Interrupt socket connection: notify the server or client to stop receiving and sending data. (Server side and client side)

int shutdown(SOCKET s, int how) 

s is the socket to be disconnected.
How to describe what operations are prohibited, the values ​​are: SD_RECEIVE, SD_SEND, SD_BOTH.

#define SD_RECEIVE 0x00 
#define SD_SEND 0x01 
#define SD_BOTH 0x02 

usage:

int nResult= shutdown(s,SD_BOTH); 
if(nResult==SOCKET_ERROR) 
{ 
//Error handling} 

10. Close socket: Release the resources occupied. (Server side and client side)

int closesocket( SOCKET s ) 

s is the socket to be closed.

usage:

int nResult=closesocket(s); 
if(nResult==SOCKET_ERROR) 
{ 
//Error handling} 

Some functions related to socket

1. Read the current error value: Every time an error occurs, if you want to deal with specific problems, you should call this function to obtain the error code.

   int WSAGetLastError(void ); 
   #define h_errno  WSAGetLastError() 

Please read the error value yourself.

2. Convert the unsigned long value of the host to network byte order (32 bits): Why do you need to do this? Because different computers use different byte order to store data. Therefore, any reference to the IP address and port number from the Winsock function and the IP address and port number passed to the Winsock function are organized in network order.

u_long htonl(u_long hostlong); 

For example:

htonl(0)=0 
 htonl(80)= 1342177280 

3. Convert unsigned long number from network byte order to host byte order, which is the inverse function of the above function.

 u_long ntohl(u_long netlong); 

For example:

ntohl(0)=0 
   ntohl(1342177280)= 80 

4. Convert the unsigned short value of the host to the network byte order (16 bits): the same reason as 2: u_short  htons(u_short hostshort);

For example:

htonl(0)=0 
   htonl(80)= 20480 


5. Convert unsigned short number from network byte order to host byte order, which is the inverse function of the above function.

 u_short ntohs(u_short netshort); 

For example:

ntohs(0)=0 
ntohsl(20480)= 80 

6. Translate the IP address divided by dots to the address of the in_addr structure. The definition of this structure is shown in Note (I), which is actually an unsigned long value. The computer processed IP addresses internally but did not recognize data such as 192.1.8.84.

unsigned long inet_addr( const char FAR * cp ); 

For example:

inet_addr("192.1.8.84")=1409810880 
   inet_addr("127.0.0.1")= 16777343 

If an error occurs, the function returns the INADDR_NONE value.

7. The IP address that translates the network address bits into points is the inverse function of the above function.

char FAR * inet_ntoa( struct in_addr in ); 

For example:

char * ipaddr=NULL; 
   char addr[20]; 
   in_addr inaddr; 
   inaddr. s_addr=16777343; 
   ipaddr= inet_ntoa(inaddr); 
   strcpy(addr,ipaddr); 

In this way, the value of addr becomes 127.0.0.1.

Be careful not to modify the return value or perform release actions. If the function fails, the NULL value will be returned.

8. Get the local address structure of the socket:

int getsockname(SOCKET s, struct sockaddr FAR * name, int FAR * namelen ); 

s is socket

name is the address value obtained after function call

namelen is the size of the buffer.

9. Get the end address structure connected to the socket:

int getpeername(SOCKET s, struct sockaddr FAR * name, int FAR * namelen ); 

s is socket

name is the end address value obtained after function call

namelen is the size of the buffer.

10. Obtain the computer name:

int gethostname( char FAR * name, int namelen ); 

name is the buffer that stores the computer name.
namelen is the size of the buffer

Usage:

   char szName[255]; 
   memset(szName,0,255); 
   if(gethostname(szName,255)==SOCKET_ERROR) 
   { 
           //Error handling   } 

The return value is: szNmae="xiaojin"

11. Obtain the host address based on the computer name:

struct hostent FAR * gethostbyname( const char FAR * name ); 

name is the computer name.

Usage:

   hostent * host; 
   char* ip; 
   host= gethostbyname("xiaojin"); 
   if(host->h_addr_list[0]) 
   { 
       struct in_addr addr; 
       memmove(&addr, host->h_addr_list[0],4); 
       //Get standard IP address       ip=inet_ ntoa (addr); 
   } 

The return value is: hostent->h_name="xiaojin"
          hostent->h_addrtype=2    //AF_INET
          hostent->length=4
          ip="127.0.0.1"

Winsock’s I/O operation:

1. Two I/O modes

  1. Blocking mode: Waiting will be done before the I/O operation is completed, and control will not be handed over to the program. Sockets default to blocking mode. It can be processed through multi-threading technology.
  2. Non-blocking mode: When performing I/O operations, the Winsock function returns and hands over control. This mode is more complicated to use, because the function returns before the run is completed, and will continue to return WSAEWOULDBLOCK errors. But powerful.

To solve this problem, some I/O models for I/O operations are proposed. The three most common types are introduced below:

2. Select model:

By calling the select function, you can determine the status of one or more sockets, and determine whether there is data on the socket, or whether data can be written to a socket.

   int select( int nfds, fd_set FAR * readfds, fd_set FAR * writefds, 
   fd_set FAR *exceptfds, const struct timeval FAR * timeout ); 

◆Let’s first look at the definition of the structure involved:

a. d_set structure:

#define FD_SETSIZE 64? 
typedef struct fd_set { 
u_int fd_count; /* how many are SET? */ 
SOCKET fd_array[FD_SETSIZE]; /* an array of SOCKETs */ 
} fd_set;  

fd_count is the number of sockets that have been set

fd_array is the socket list, FD_SETSIZE is the maximum socket number, and it is recommended that no less than 64. This is what Microsoft recommends.

B. Timeval structure:

struct timeval { 
long tv_sec; /* seconds */ 
long tv_usec; /* and microseconds */ 
}; 

tv_sec is the second value of time.

tv_usec is the millisecond value of time.

This structure mainly sets the waiting value of the select() function. If the structure is set to (0,0), the select() function will return immediately.

◆Let’s take a look at the functions of each parameter of the select function:

1.           nfds: It has no use, it is mainly used for system compatibility, and is generally set to 0.
2.
3.
4.
5.            timeout: timeout.
6. The return value of the function failed: the call failed and returns SOCKET_ERROR, and the timeout returns 0.

There are at least one of the three variables readfds, writefds, and exceptfds that are not empty. At the same time, this non-empty socket group has at least one socket. The reason is very simple, otherwise what should I choose? Example: Test whether a socket is readable:

fd_set fdread; 
//FD_ZERO definition// #define FD_ZERO(set) (((fd_set FAR *)(set))->fd_count=0) 
FD_ZERO(&fdread); 
FD_SET(s,&fdread); //Add to socket, please see the detailed definitionif(select(0,%fdread,NULL,NULL,NULL)>0 
{ 
    //success    if(FD_ISSET(s,&fread) //If there is a fread, please see the detailed definition    { 
        //It is readable    } 
} 

◆I/O operation function: mainly used to obtain operation parameters related to sockets.

int ioctlsocket(SOCKET s, long cmd, u_long FAR * argp ); 

s is a socket for I/O operation.

cmd is an operation command on the socket.

argp is a pointer to the parameters taken by the command.

Common commands:

//Determine the amount of data automatically read in the socket#define FIONREAD _IOR(''''f'''', 127, u_long) /* get # bytes to read */ 
//Allow or disable the non-blocking mode of sockets, allow to be non-0, and prohibit to be 0#define FIONBIO _IOW(''''f'''', 126, u_long) /* set/clear non-blocking i/o */ 
//Determine whether all out-of-band data has been read in#define SIOCATMARK _IOR(''''s'''', 7, u_long) /* at oob mark? */ 

3. WSAAsyncSelect model:

The WSAAsyncSelect model is also a commonly used asynchronous I/O model. Applications can receive notifications of network events based on WINDOWS messages on a socket. The implementation method of this model is to automatically set the socket to non-blocking mode by calling the WSAAsyncSelect function, register one or more network times with WINDOWS, and provide a window handle to use when notifications. When the registered event occurs, the corresponding window will receive a message-based notification.

int WSAAsyncSelect( SOCKET s, HWND hWnd, u_int wMsg, long lEvent);    

s is a socket that requires event notification

hWnd is the window handle for receiving the message

wMsg is the message to be received

lEvent is a mask, specifying the combination of network events that the application is interested in, mainly as follows:

#define FD_READ_BIT 0 
#define FD_READ (1 << FD_READ_BIT) 
#define FD_WRITE_BIT 1 
#define FD_WRITE (1 << FD_WRITE_BIT) 
#define FD_OOB_BIT 2 
#define FD_OOB (1 << FD_OOB_BIT) 
#define FD_ACCEPT_BIT 3 
#define FD_ACCEPT (1 << FD_ACCEPT_BIT) 
#define FD_CONNECT_BIT 4 
#define FD_CONNECT (1 << FD_CONNECT_BIT) 
#define FD_CLOSE_BIT 5 
#define FD_CLOSE (1 << FD_CLOSE_BIT) 

Usage: To receive read and write notifications:

int nResult= WSAAsyncSelect(s,hWnd,wMsg,FD_READ|FD_WRITE); 
if(nResult==SOCKET_ERROR) 
{ 
    //Error handling} 

Cancellation notice:

int nResult= WSAAsyncSelect(s,hWnd,0,0); 

When the application window hWnd receives a message, the parameters identify the socket, the low word of lParam indicates the network event, and the high word contains the error code.

4. WSAEventSelect Model

The WSAEventSelect model is similar to the WSAAsyncSelect model, but the main difference is that when a network event occurs, it will be sent to an event object handle, rather than to a window.

The steps for use are as follows:

a. Create an event object to receive network events:

#define WSAEVENT HANDLE 
#define LPWSAEVENT LPHANDLE 
WSAEVENT WSACreateEvent( void ); 

The return value of this function is an event object handle, which has two working states: signed and nonsignaled, and two working modes: manual reset and automatic reset. Defaults to the untransmitted working state and manual reset mode.

b. Associate the event object with the socket and register the event at the same time, so that the working state of the event object has never been transferred to the message.
A message has been sent.

int WSAEventSelect( SOCKET s,WSAEVENT hEventObject,long lNetworkEvents );  

s is a socket

hEventObject is the event object handle just created

lNetworkEvents is the mask, defined as described above

c. After I/O processing, set the event object to not transmitted message

BOOL WSAResetEvent( WSAEVENT hEvent ); 

Hevent is an event object

Returns TRUE successfully, and returns FALSE after failure.

d. Wait for network events to trigger the working state of the event handle:

DWORD WSAWaitForMultipleEvents( DWORD cEvents, 
const WSAEVENT FAR * lphEvents, BOOL fWaitAll, 
DWORD dwTimeout, BOOL fAlertable ); 

lpEvent is a pointer to the event handle array

cEvent is the number of event handles, and its maximum value is WSA_MAXIMUM_WAIT_EVENTS

fWaitAll specifies the waiting type: TRUE: Return when the lphEvent array replicates all event objects at the same time;

FALSE: Return any event if there is a signal.

dwTimeout is waiting timeout (milliseconds)

fAlertable is whether to execute the completion routine when the function returns.

When referring to events in the event array, you should use the return value of WSAWaitForMultipleEvents, subtract the pre-declared value WSA_WAIT_EVENT_0 to obtain the specific reference value. For example:

nIndex=WSAWaitForMultipleEvents(…); 
MyEvent=EventArray[Index- WSA_WAIT_EVENT_0]; 

e. Determine the type of network event:

int WSAEnumNetworkEvents( SOCKET s, 
WSAEVENT hEventObject, LPWSANETWORKEVENTS lpNetworkEvents ); 

s is a socket

hEventObject is an event object that needs to be reset

lpNetworkEvents is a logging network events and error codes, and its structure is defined as follows:

typedef struct _WSANETWORKEVENTS { 
    long lNetworkEvents; 
    int iErrorCode[FD_MAX_EVENTS]; 
} WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS; 

f. Close the event object handle:

BOOL WSACloseEvent(WSAEVENT hEvent); 

The call returns TRUE, otherwise it returns FALSE.

The above is all the content of this article. I hope it will be helpful to everyone's study and I hope everyone will support me more.