Analysis: setsockopt () improves the robustness of Socket network programs

Source: Internet
Author: User

1. If the socket is already in the established State (usually distinguished by the port number and flag ),
Closesocket (usually does not close immediately and goes through the time_wait process) and wants to continue to reuse the socket:
Bool breuseaddr = true;
Setsockopt (S, sol_socket, so_reuseaddr, (const char *) & amp; breuseaddr, sizeof (bool ));

2. If you want to force close a soket that is already in the connection status after you call closesocket
Time_wait process:
Bool bdontlinger = false;
Setsockopt (S, sol_socket, so_dontlinger, (const char *) & amp; bdontlinger, sizeof (bool ));

3. In the send () and Recv () processes, sometimes due to network conditions and other reasons, sending and receiving cannot be performed as expected, but set the sending and receiving time limit:
Int nnettimeout = 1000; // 1 second
// Sending time limit
Setsockopt (socket, sol_s0cket, so_sndtimeo, (char *) & amp; nnettimeout, sizeof (INT ));
// Receiving time limit
Setsockopt (socket, sol_s0cket, so_rcvtimeo, (char *) & amp; nnettimeout, sizeof (INT ));

4. When sending (), the returned bytes are actually sent (synchronized) or the bytes sent to the socket buffer.
(Asynchronous); by default, the system sends and receives data in 8688 bytes (about 8.5 KB) at a time.
When receiving a large amount of data, you can set a socket buffer to avoid the continuous cyclic sending and receiving of send () and Recv:
// Receiving buffer
Int nrecvbuf = 32*1024; // set it to 32 K
Setsockopt (S, sol_socket, so_rcvbuf, (const char *) & amp; nrecvbuf, sizeof (INT ));
// Sending Buffer
Int nsendbuf = 32*1024; // set it to 32 K
Setsockopt (S, sol_socket, so_sndbuf, (const char *) & amp; nsendbuf, sizeof (INT ));

5. If you want to avoid the impact of copying data from the system buffer to the socket buffer when sending data
Program performance:
Int nzero = 0;
Setsockopt (socket, sol_s0cket, so_sndbuf, (char *) & amp; nzero, sizeof (nzero ));

6. Complete the preceding functions in Recv (). By default, the socket buffer content is copied to the system buffer ):
Int nzero = 0;
Setsockopt (socket, sol_s0cket, so_rcvbuf, (char *) & amp; nzero, sizeof (INT ));

7. Generally, when sending a UDP datagram, you want the data sent by the socket to have the broadcast feature:
Bool bbroadcast = true;
Setsockopt (S, sol_socket, so_broadcast, (const char *) & amp; bbroadcast, sizeof (bool ));

8. When the client connects to the server, if the socket in non-blocking mode is in the connect () process
To set the connect () latency until accpet () is called (this function is set only when there is a significant non-blocking process)
Function does not play a major role in blocked function calls)
Bool bconditionalaccept = true;
Setsockopt (S, sol_socket, so_conditional_accept, (const char *) & amp; bconditionalaccept, sizeof (bool ));

9. If closesocket () is called while sending data (sending () is not completed, and data is not sent ),
The general measure is to "calmly close" Shutdown (S, sd_both), but the data is definitely lost. How to set the program to meet specific requirements?
Application requirements (that is, disable the socket after sending the unsent data )?
Struct linger {
U_short l_onoff;
U_short l_linger;
};
Linger m_slinger;
M_slinger.l_onoff = 1; // (allowed to stay when closesocket () is called, but there is still data not sent)
// If m_slinger.l_onoff = 0, the function is the same as 2;
M_slinger.l_linger = 5; // (the allowable stay time is 5 seconds)
Setsockopt (S, sol_socket, so_linger, (const char *) & amp; m_slinger, sizeof (linger ));
Note: 1. when the latency is set for a non-blocking socket, it is not very useful, it is best not to use; 2. if you want the program to experience so_linger, you need to set so_dontlinger, or set l_onoff = 0;

10. A program that is rarely used in SDI or dialog can record the debugging information of socket:
(I tested this function not long ago, and the mode information can be saved, including the parameters during socket creation.
Specific protocols and error code can be recorded)
Bool bdebug = true;
Setsockopt (S, sol_socket, so_debug, (const char *) & amp; bdebug, sizeof (bool ));

11. Additional: the buffer size is usually set through setsockopt (), but it cannot meet the data transmission requirements,
My habit is to write a class for processing network buffering and dynamically allocate memory. The general habit is to write a class for processing network buffering and dynamically allocate memory; I will write this class below, hoping to help you:
 
// Rewrite the string format.
// ================================================ ==========================================================
// Binary data, mainly used to send and receive data in the network buffer zone
// The source code of the MFC-type cstring is rewritten as the source code of the cstring. Its usage is similar to that of the cstring,
// However, the pure binary data is stored in the CIDR block, and '/0' is not used as the end mark.
// The data length can be obtained through getlength (), and the buffer address can be obtained through the lpbyte operator.
 
 
// ================================================ ==========================================================
// Copyright (c) All-vision Corporation. All rights reserved.
// Module: netobject
// File: simpleiobuffer. h
// Author: gdy119
// Email: 8751webmaster@126.com
// Date: 2004.11.26
// ================================================ ==========================================================
// Netiobuffer. h
# Ifndef _ netiobuffer_h
# DEFINE _ netiobuffer_h
// ================================================ ========================================================
# Define max_buffer_length 1024*1024
// ================================================ ========================================================
// Mainly used to process network buffer data
Class cntiobuffer
{
Protected:
Lpbyte m_pbindata;
Int m_nlength;
Int m_ntotallength;
Critical_section m_cs;
Void initvalibers ();
Public:
Nntiobuffer ();
Nntiobuffer (const lpbyte lbbyte, int nlength );
Cidrbuffer (const cidrbuffer & binarysrc );
Virtual ~ Nntiobuffer ();
// ================================================ ========================================================
Bool copydata (const lpbyte lbbyte, int NLE
---------------------------------------------------------------
 
In fact, I think 5th entries should be worth noting.
Int nzero = 0;
Setsockopt (socket, sol_s0cket, so_sndbuf, (char *) & nzero, sizeof (nzero ));
 
I remember some of my friends mentioned that although the socket was successfully sent, it was actually only sent to the data buffer, but it was not actually sent on the physical device. Through this statement, set the sending buffer to 0, that is, after the sending buffer is blocked, once the sending is returned (of course, it is blocked ), it can be confirmed that the data has been sent ^ _ ^, but this may affect the system performance.
 
---------------------------------------------------------------
 
When setoptsock () is set to port multiplexing, it is easy to cause harm to some programs without separate bind mode.
For example, the Old Ping ICMP door, after a simple sniffer, receives the packet, then sets the setoptsock bind web service, and then creates a cmd process bind and then port 80.

 

==============================================

Example code

The following example demonstratesSetsockoptFunction.

# Include <stdio. h>
# Include "winsock2.h"

Void main (){

//---------------------------------------
// Declare Variables
Wsadata;
Socket listensocket;
Sockaddr_in service;

//---------------------------------------
// Initialize Winsock
Int iresult = wsastartup (makeword (2, 2), & wsadata );
If (iresult! = No_error)
Printf ("error at wsastartup/N ");

//---------------------------------------
// Create a listening socket
Listensocket = socket (af_inet, sock_stream, ipproto_tcp );
If (listensocket = invalid_socket ){
Printf ("error at socket ()/n ");
Wsacleanup ();
Return;
}

//---------------------------------------
// Bind the socket to the local IP Address
// And port 27015
Hostent * thishost;
Char * IP;
U_short port;
Port = 27015;
Thishost = gethostbyname ("");
IP = inet_ntoa (* (struct in_addr *) * thishost-> h_addr_list );

Service. sin_family = af_inet;
Service. sin_addr.s_addr = inet_addr (IP );
Service. sin_port = htons (port );

If (BIND (listensocket, (sockaddr *) & service, sizeof (Service) = socket_error ){
Printf ("bind failed/N ");
Closesocket (listensocket );
Return;
}

//---------------------------------------
// Initialize variables and callSetsockopt.
// The so_keepalive parameter is a socket option
// That makes the socket send keepalive messages
// On the session. The so_keepalive socket option
// Requires a Boolean value to be passed to
//SetsockoptFunction. If true, the socket is
// Configured to send keepalive messages, if false
// The socket configured to not send keepalive messages.
// This section of code testsSetsockoptFunction
// By checking the status of so_keepalive on the socket
// Using the getsockopt function.
Bool boptval = true;
Int boptlen = sizeof (bool );
Int ioptval;
Int ioptlen = sizeof (INT );

If (getsockopt (listensocket, sol_socket, so_keepalive, (char *) & ioptval, & ioptlen )! = Socket_error ){
Printf ("so_keepalive value: % LD/N", ioptval );
}

If (Setsockopt(Listensocket, sol_socket, so_keepalive, (char *) & boptval, boptlen )! = Socket_error ){
Printf ("set so_keepalive: On/N ");
}

If (getsockopt (listensocket, sol_socket, so_keepalive, (char *) & ioptval, & ioptlen )! = Socket_error ){
Printf ("so_keepalive value: % LD/N", ioptval );
}

Wsacleanup ();
Return;

}

Notes for IrDA sockets

Keep in mind the following:

The af_irda.h header file must be explicitly encoded ded.
IRDA provides the following settable socket option:
Value Type meaning
Irlmp_ias_set * ias_set sets IAS attributes

The irlmp_ias_set socket option enables the application to set a single attribute of a single class in the local IAS. the application specifies the class to set, the attribute, and attribute type. the application is expected to allocate a buffer of the necessary size for the passed parameters.

IRDA provides an IAS database that stores IrDA-based information. limited access to the IAS database is available through the Windows Sockets 2 interface, but such access is not normally used by applications, and exists primarily to support connections to non-Windows devices that are not compliant with the Windows Sockets 2 IrDA conventions.

The following structure, ias_set, is used with the irlmp_ias_setSetsockoptOption to manage the local IAS database:

Typedef struct _ ias_set {
Char irdaclassname [ias_max_classname];
Char irdaattribname [ias_max_attribname];
U_long irdaattribtype;
Union
{
Long irdaattribint;
Struct
{
U_short Len;
U_char octetseq [ias_max_octet_string];
} Irdaattriboctetseq;
Struct
{
U_char Len;
U_char charset;
U_char usrstr [ias_max_user_string];
} Irdaattribusrstr;
} Irdaattribute;
} Ias_set, * pias_set, far * lpias_set;

The following structure, ias_query, is used with the irlmp_ias_querySetsockoptOption to query a peer's IAS database:

Typedef struct _ windows_ias_query {
U_char irdadeviceid [4];
Char irdaclassname [ias_max_classname];
Char irdaattribname [ias_max_attribname];
U_long irdaattribtype;
Union
{
Long irdaattribint;
Struct
{
U_long Len;
U_char octetseq [ias_max_octet_string];
} Irdaattriboctetseq;
Struct
{
U_long Len;
U_long charset;
U_char usrstr [ias_max_user_string];
} Irdaattribusrstr;
} Irdaattribute;
} Ias_query, * pias_query, far * lpias_query;

Required SO _ Level socket options are not meaningful to IrDA. Only so_linger is specifically supported.

NoteSetsockoptMust be called before bind on Windows NT 4.0, Windows 95, and Windows 98 platforms.

Requirements
Client requires Windows XP, Windows 2000 Professional, Windows NT Workstation, Windows ME, Windows 98, or Windows 95.
Server requires Windows Server 2003, Windows 2000 server, or Windows NT Server.
Header declared in winsock2.h.

Library link to ws2_32.lib.

DLL requires ws2_32.dll.

 

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.