Set the sending and receiving buffer of the socket

Source: Internet
Author: User

Subject: Analysis: setsockopt () improves program robustness
Author: gdy119 (evening breeze)

I am sorry for the constant thanks from coolmei25 (Mei Sheng). below
I have written some of my experiences in network programming and hope to help him (^_^:
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 *) & 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 *) & 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 *) & nnettimeout, sizeof (INT ));
// Receiving time limit
Setsockopt (socket, sol_s0cket, so_rcvtimeo, (char *) & 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 *) & nrecvbuf, sizeof (INT ));
// Sending Buffer
Int nsendbuf = 32*1024; // set it to 32 K
Setsockopt (S, sol_socket, so_sndbuf, (const char *) & 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 *) & 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 *) & 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 *) & 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 *) & 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 *) & 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 it;
2. If you want the program to not 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 *) & 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. Below I will write this class and hope
Beginners help:

// 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_sectionm_cs;
Void initvalibers ();
Public:
Nntiobuffer ();
Nntiobuffer (const lpbyte lbbyte, int nlength );
Cidrbuffer (const cidrbuffer & binarysrc );
Virtual ~ Nntiobuffer ();
// ================================================ ========================================================
Bool copydata (const lpbyte lbbyte, int nlength );
Bool concatdata (const lpbyte lbbyte, int nlength );
Void resetiobuffer ();
Int getlength () const;
Bool setlength (INT nlen );
Lpbyte getcurpos ();
Int getremainlen ();
Bool isempty () const;
Operator lpbyte () const;
Static getmaxlength () {return max_buffer_length ;}
Const nntiobuffer & operator = (const nntiobuffer & buffsrc );
};
# Endif //
// Netobuffer. cpp: Implementation of the same class.
// ================================================ ======================================
# Include "stdafx. H"
# Include "netiobuffer. H"
// ================================================ ======================================
// ================================================ ======================================
// Construction/destruction
CIDR Block: CIDR Block ()
{
Initvalibers ();

}
Cidrbuffer: cidrbuffer (const lpbyte lbbyte, int nlength)
{
Initvalibers ();
Copydata (lbbyte, nlength );
}
Nntiobuffer ::~ Nntiobuffer ()
{
Delete [] m_pbindata;
M_pbindata = NULL;
Deletecriticalsection (& m_cs );

}
Cidrbuffer: cidrbuffer (const: cidrbuffer & binarysrc)
{

Initvalibers ();
Copydata (binarysrc, binarysrc. getlength ());

}
Void MAID: initvalibers ()
{

M_pbindata = NULL;
M_nlength = 0;
M_ntotallength = max_buffer_length;
If (m_pbindata = NULL)
{
M_pbindata = new byte [m_ntotallength];
Assert (m_pbindata! = NULL );
}
Initializecriticalsection (& m_cs );
}
Void MAID: resetiobuffer ()
{
Entercriticalsection (& m_cs );
M_nlength = 0;
Memset (m_pbindata, 0, m_ntotallength );
Leavecriticalsection (& m_cs );
}

Bool nntiobuffer: copydata (const lpbyte lbbyte, int nlength)
{
If (nlength> max_buffer_length)
Return false;

Resetiobuffer ();
Entercriticalsection (& m_cs );
Memcpy (m_pbindata, lbbyte, nlength );
M_nlength = nlength;
Leavecriticalsection (& m_cs );

Return true;
}

Bool nntiobuffer: concatdata (const lpbyte lbbyte, int nlength)
{
If (m_nlength + nlength> max_buffer_length)
Return false;

Entercriticalsection (& m_cs );
Memcpy (m_pbindata + m_nlength, lbbyte, nlength );
M_nlength + = nlength;
Leavecriticalsection (& m_cs );

Return true;
}

Int MAID: getlength () const
{
Return m_nlength;
}

Bool nntiobuffer: setlength (INT nlen)
{
If (nlen> max_buffer_length)
Return false;

Entercriticalsection (& m_cs );
M_nlength = nlen;
Leavecriticalsection (& m_cs );

Return true;
}

Lpbyte MAID: getcurpos ()
{

If (m_nlength <max_buffer_length)

Return (m_pbindata + m_nlength );

Else
Return NULL;
}

Nntiobuffer: Operator lpbyte () const
{
Return m_pbindata;
}

Int MAID: getremainlen ()
{

Return max_buffer_length-m_nlength;

}
Bool nntiobuffer: isempty () const
{
Return m_nlength = 0;
}

Const MAID: Operator = (const maid & buffsrc)
{
If (& buffsrc! = This)
{
Copydata (buffsrc, buffsrc. getlength ());

}
Return * this;

}

Reply to: piggyxp ([Pig] ● VC, ●) () reputation: 204

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.

To: Sander ()
UDP also has a copy process, but the maximum UDP packet size is 64 KB;
Tcp_nodelay is generally used on the normal data stream;
12. When sending data, it is generally sent after the system buffer is full. Now it is set as long as the system
The buffer zone sends data immediately:
Bool bnodelay = true;
Setsockopt (S, ipproto_tcp, tcp_nodelay, (const char *) & bnodelayt, sizeof (bool ));

Respondent: od4ys (Fengfeng) () Credit: 100

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.

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.