1. 程式人生 > >setsockopt()選項改善程式的健壯性

setsockopt()選項改善程式的健壯性

寫出我在網路程式設計中的一點心得體會,希望對他(^_^也對大家)有幫助:
1. 如果在已經處於 ESTABLISHED狀態下的socket(一般由埠號和標誌符區分)呼叫
closesocket(一般不會立即關閉而經歷TIME_WAIT的過程)後想繼續重用該socket:
BOOL bReuseaddr=TRUE;
setsockopt(s,SOL_SOCKET ,SO_REUSEADDR,(const char*)&bReuseaddr,sizeof(BOOL));
2. 如果要已經處於連線狀態的soket在呼叫closesocket後強制關閉,不經歷
TIME_WAIT的過程:
BOOL bDontLinger = FALSE; 

setsockopt(s,SOL_SOCKET,SO_DONTLINGER,(const char*)&bDontLinger,sizeof(BOOL));
3.在send(),recv()過程中有時由於網路狀況等原因,發收不能預期進行,而設定收發時限:
int nNetTimeout=1000;//1秒
//傳送時限
setsockopt(socket,SOL_S0CKET,SO_SNDTIMEO,(char *)&nNetTimeout,sizeof(int));
//接收時限
setsockopt(socket,SOL_S0CKET,SO_RCVTIMEO,(char *)&nNetTimeout,sizeof(int));

4.在send()的時候,返回的是實際傳送出去的位元組(同步)或傳送到socket緩衝區的位元組
(非同步);系統預設的狀態傳送和接收一次為8688位元組(約為8.5K);在實際的過程中傳送資料
和接收資料量比較大,可以設定socket緩衝區,而避免了send(),recv()不斷的迴圈收發:
// 接收緩衝區
int nRecvBuf=32*1024;//設定為32K
setsockopt(s,SOL_SOCKET,SO_RCVBUF,(const char*)&nRecvBuf,sizeof(int));
//傳送緩衝區
int nSendBuf=32*1024;//設定為32K
setsockopt(s,SOL_SOCKET,SO_SNDBUF,(const char*)&nSendBuf,sizeof(int));

5. 如果在傳送資料的時,希望不經歷由系統緩衝區到socket緩衝區的拷貝而影響
程式的效能:
int nZero=0;
setsockopt(socket,SOL_S0CKET,SO_SNDBUF,(char *)&nZero,sizeof(nZero));
6.同上在recv()完成上述功能(預設情況是將socket緩衝區的內容拷貝到系統緩衝區):
int nZero=0;
setsockopt(socket,SOL_S0CKET,SO_RCVBUF,(char *)&nZero,sizeof(int));
7.一般在傳送UDP資料報的時候,希望該socket傳送的資料具有廣播特性:
BOOL bBroadcast=TRUE; 
setsockopt(s,SOL_SOCKET,SO_BROADCAST,(const char*)&bBroadcast,sizeof(BOOL));
8.在client連線伺服器過程中,如果處於非阻塞模式下的socket在connect()的過程中可
以設定connect()延時,直到accpet()被呼叫(本函式設定只有在非阻塞的過程中有顯著的
作用,在阻塞的函式呼叫中作用不大)
BOOL bConditionalAccept=TRUE;
setsockopt(s,SOL_SOCKET,SO_CONDITIONAL_ACCEPT,(const char*)&bConditionalAccept,sizeof(BOOL));
9.如果在傳送資料的過程中(send()沒有完成,還有資料沒傳送)而呼叫了closesocket(),以前我們
一般採取的措施是"從容關閉"shutdown(s,SD_BOTH),但是資料是肯定丟失了,如何設定讓程式滿足具體
應用的要求(即讓沒發完的資料傳送出去後在關閉socket)?
struct linger {
u_short l_onoff;
u_short l_linger;
};
linger m_sLinger;
m_sLinger.l_onoff=1;//(在closesocket()呼叫,但是還有資料沒傳送完畢的時候容許逗留)
// 如果m_sLinger.l_onoff=0;則功能和2.)作用相同;
m_sLinger.l_linger=5;//(容許逗留的時間為5秒)
setsockopt(s,SOL_SOCKET,SO_LINGER,(const char*)&m_sLinger,sizeof(linger));
Note:1.在設定了逗留延時,用於一個非阻塞的socket是作用不大的,最好不用;
2.如果想要程式不經歷SO_LINGER需要設定SO_DONTLINGER,或者設定l_onoff=0;
10.還一個用的比較少的是在SDI或者是Dialog的程式中,可以記錄socket的除錯資訊:
(前不久做過這個函式的測試,調式資訊可以儲存,包括socket建立時候的引數,採用的
具體協議,以及出錯的程式碼都可以記錄下來)
BOOL bDebug=TRUE;
setsockopt(s,SOL_SOCKET,SO_DEBUG,(const char*)&bDebug,sizeof(BOOL));
11.附加:往往通過setsockopt()設定了緩衝區大小,但還不能滿足資料的傳輸需求,
我的習慣是自己寫個處理網路緩衝的類,動態分配記憶體;下面我將這個類寫出,希望對
初學者有所幫助:

//仿照String 改寫而成
//==============================================================================
// 二進位制資料,主要用於收發網路緩衝區的資料
// CNetIOBuffer 以 MFC 類 CString 的原始碼作為藍本改寫而成,用法與 CString 類似,
// 但是 CNetIOBuffer 中存放的是純粹的二進位制資料,'\0' 並不作為它的結束標誌。
// 其資料長度可以通過 GetLength() 獲得,緩衝區地址可以通過運算子 LPBYTE 獲得。


//==============================================================================
// Copyright (c) All-Vision Corporation. All rights reserved.
// Module: NetObject
// File: SimpleIOBuffer.h
// Author: gdy119
// Email : [email protected]
// Date: 2004.11.26
//==============================================================================
// NetIOBuffer.h
#ifndef _NETIOBUFFER_H
#define _NETIOBUFFER_H
//=============================================================================
#define MAX_BUFFER_LENGTH 1024*1024
//=============================================================================
//主要用來處理網路緩衝的資料
class CNetIOBuffer 
{
protected:
LPBYTE m_pbinData;
int m_nLength;
int m_nTotalLength;
CRITICAL_SECTIONm_cs;
void Initvalibers();
public:
CNetIOBuffer();
CNetIOBuffer(const LPBYTE lbbyte, int nLength);
CNetIOBuffer(const CNetIOBuffer&binarySrc);
virtual ~CNetIOBuffer();
//=============================================================================
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 CNetIOBuffer& operator=(const CNetIOBuffer& buffSrc);
};
#endif // 
// NetOBuffer.cpp: implementation of the CNetIOBuffer class.
//======================================================================
#include "stdafx.h"
#include "NetIOBuffer.h"
//======================================================================
//=======================================================================
// Construction/Destruction
CNetIOBuffer::CNetIOBuffer()
{
Initvalibers();

}
CNetIOBuffer::CNetIOBuffer(const LPBYTE lbbyte, int nLength)
{
Initvalibers();
CopyData(lbbyte, nLength);
}
CNetIOBuffer::~CNetIOBuffer()
{
delete []m_pbinData;
m_pbinData=NULL;
DeleteCriticalSection(&m_cs);

}
CNetIOBuffer::CNetIOBuffer(const CNetIOBuffer&binarySrc)
{

Initvalibers();
CopyData(binarySrc,binarySrc.GetLength());

}
void CNetIOBuffer::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 CNetIOBuffer::ResetIoBuffer()
{
EnterCriticalSection(&m_cs);
m_nLength = 0;
memset(m_pbinData,0,m_nTotalLength);
LeaveCriticalSection(&m_cs);
}

BOOL CNetIOBuffer::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 CNetIOBuffer::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 CNetIOBuffer::GetLength() const
{
return m_nLength;
}

BOOL CNetIOBuffer::SetLength(int nLen)
{
if( nLen > MAX_BUFFER_LENGTH )
return FALSE;

EnterCriticalSection(&m_cs);
m_nLength = nLen;
LeaveCriticalSection(&m_cs);

return TRUE;
}

LPBYTE CNetIOBuffer::GetCurPos()
{

if( m_nLength < MAX_BUFFER_LENGTH )

return (m_pbinData+m_nLength);

else
return NULL;
}

CNetIOBuffer:: operator LPBYTE() const
{
return m_pbinData;
}

int CNetIOBuffer::GetRemainLen()
{

return MAX_BUFFER_LENGTH - m_nLength;

}
BOOL CNetIOBuffer::IsEmpty() const
{
return m_nLength == 0;
}

const CNetIOBuffer& CNetIOBuffer:: operator=(const CNetIOBuffer& buffSrc)
{
if(&buffSrc!=this)
{
CopyData(buffSrc, buffSrc.GetLength());

}
return *this;

}



12.傳送資料時候一般是系統緩衝區滿以後才傳送,現在設定為只要系統
緩衝區有資料就立刻傳送: 
BOOL bNodelay=TRUE;
SetSockOpt(s,IPPROTO_TCP,TCP_NODELAY,(const char*)&bNodelayt,sizeof(BOOL));

附加:
setoptsock()這個函式 設定成埠複用的時候,很容易對一些沒有進行單獨bind模式的程式造成危害。

比如old的 ping icmp door,簡單的sniffer後,收到包,然後設定setoptsock bind web服務,然後建立個cmd程序 bind再80埠。

轉自:http://www.cppblog.com/jjbird/articles/6221.html

相關推薦

setsockopt()選項改善程式健壯

寫出我在網路程式設計中的一點心得體會,希望對他(^_^也對大家)有幫助:1. 如果在已經處於 ESTABLISHED狀態下的socket(一般由埠號和標誌符區分)呼叫closesocket(一般不會立即關閉而經歷TIME_WAIT的過程)後想繼續重用該socket:BOOL

異常處理(程式健壯→功能→效能)

  異常 (Exception):發生於程式執行期間,表明出現了一個非法的執行狀況。許多JDK中的方法在檢測到非法情況時,都會丟擲一個異常物件。例如:陣列越界和被0除。 try{   //可能發生執行錯誤的程式碼;  }  

PHP程式設計過程中程式健壯(自己總結筆記記錄)

在php業務開發中,因為IDE對於php的異常不會像java編輯器IDE那樣智慧自動加上異常捕獲,這時候就需要我們開發的時候手動加上異常捕獲,這樣可以儘可能的保證程式的健壯性。避免反饋到使用者端的是程式異常。下面是自己親測的示例: SelfException.php的程式碼如下: class

【高質量C++/C總結5】const常用用法-提高程式健壯

說在開始: 我提煉了《C++ Primer》、《侯捷C++》、《高質量程式設計指南——C/C++語言》等資料中的重要部分,並總結成此博文。其中涉及到許多我個人對C++的理解,如若有不合理之處,還請朋友們多多指出,我會虛心接受每一個建議。同時,我將實現程式碼放到了我的GitHub上ht

驅動程式健壯考慮

驅動程式的健壯性要考慮硬體出問題的時候不會導致核心的工作異常。比如驅動註冊的時候要對硬體的識別,裝置硬體是否存在或者硬體是否正常。如果硬體模組不正常,但是還要去註冊,訪問的時候會出現問題,如果處理不當會導致核心CRAS

【架構設計】【程式指標】魯棒健壯的細節區別

  寫一段功能性的程式碼,可能需要一百行程式碼,但是寫一段健壯的程式,至少需要300行程式碼。例如:房貸計算器的程式碼,演算法異常簡單,十多行就完成了,但是,這段程式完全不具備健壯性,很簡單,我的輸入是不受限制的,這個程式要求從使用者介面讀取利率,年限,貸款額三個資料,一般同學的寫法很簡單,一句doubleN

論怎麼提高程式健壯

程式健壯性的提高要從設計、實現、測試三方面入手,具體來說 1. 設計 1. 系統 系統外部模組的非同步響應都需要設定超時時間,要有超時處理,超時時間要和外部模組協商一個合理時間。 傳送訊息失敗和設定timer失敗統一做處理。 需要設計相關機制(比如心跳包機制)監控程序/執行緒是否發生了堵塞,發生堵

論用例健壯的重要

做了 不同 聯想 否則 span 不能 col 等級 use 最近出了2個類似問題,此處寫下,以作為警醒 問題1: 背景:電商類網站,為了增加用戶回流,增加用戶購買力度,做了一個和用戶等級相關活動 需求:用戶等級為g0 -g5,現在有一批代金券有等級領取限制。用戶等級和代金

Python正則表達式返回首次匹配到的字符及查詢的健壯

ror exe https -m rec last first sta clas re.findall(pattern,string)會搜索所有匹配的字符,返回的是一個列表,獲取首個匹配需要re.findall(pattern,string)[0]訪問, 但是如果finda

程序的健壯及代碼風格

增加 命名規則 strong alt 用戶輸入 異常 info 圖片 src 增強程序的健壯性 在程序中增加代碼用於專門處理程序的異常情況,稱為防禦性程序設計。 保證用戶輸入的數據不小於0實例 基本的代碼風格 程序版式 標識符命名規則 註釋 程序的

【軟件構造】第七章第一節 健壯和正確性的區別

日期 center 質量 ror lan 啟動 rec 失敗 erro 第七章第一節 健壯性和正確性的區別 第七章:進入軟件構造最關鍵的質量特性 ——健壯性和正確性。 本節在1-2節的基礎上,重申了Robustness and Correctness的重要性,澄清了二者之

關於Java健壯的一些思考與實踐

try 所有 arraylist 策略 img executor 自動化 其他 返回 程序健壯性非常重要,要怎麽玩怎麽寫才能讓程序更加魯棒呢?我又這麽幾點小建議。 一、進行統一的業務處理響應 根據螞蟻金服開放平臺的標準返回,一個 response 至少應當有4個返回值。 1

使用moneykey對APP進行健壯測試

source details nor money fault 我們 lib sdk bsp 註意:moneykey對app按鈕偽隨機點擊,只能測試app穩定性和健壯性,無法進行常規測試 1、安裝 A、jdk(不詳細介紹) B、安裝配置android配置環境:Android

程序try-catch的絕對健壯之嵌套

void ati rgs 假設 主題 我們 catch 平時 sha 寫程序的過程中,我們對try-catch在熟悉不過了,捕獲異常進行處理,以保證程序的健壯性。 今日突發一想,如果我們catch中的代碼異常了怎麽辦?我們做以下一種假設 static void Main(

Algs4-1.2.17有理數實現的健壯

final als .com sce oid printf 啟用 detail 開發 1.2.17有理數實現的健壯性。在Rational(請見練習1.2.16)的開發中使用斷言來防止溢出。答:在命令行使用:java -ea 文件名 啟用斷言功能。(估計是單次啟用斷言

【轉】自動化測試框架: pytest&allure ,提高自動化健壯和穩定性

序 在之前,我寫過一個系列“從零開始搭建一個簡單的ui自動化測試框架(pytest+selenium+allure)”,在這個系列裡,主要介紹瞭如何從零開始去搭建一個可用的自動化工程框架,但是還缺乏了一些細節的補充,例如對於自動化測試而言,如何提高其測試的穩定性? 本篇文章,將會和讀者一起探討這個

異常處理(程序健壯→功能→能)

父類 位置 jdk 報錯 fin 允許 代碼 沒有 多層 異常 (Exception):發生於程序執行期間,表明出現了一個非法的運行狀況。許多JDK中的方法在檢測到非法情況時,都會拋出一個異常對象。例如:數組越界和被0除。 try{ //可能發生運行錯誤的代碼;

const提高函式健壯

看到const關鍵字,首先想到是const常量,const更大的作用是它可以修飾函式的引數、返回值,甚至函式的定義體 1.用const修飾函式的引數 如果引數做輸出用,不論他是什麼資料型別,也不論它採用指標傳遞還是引用傳遞都不能加const修飾,否則該引數將失去輸出功能。 const只能修飾

Python實踐1-Tenacity提高自動測試健壯

在自動化測試工具和自動化測試用例開發過程中,經常需要處理一些待操作物件不穩定的情況,例如,某些介面元素不能及時出現,某些服務暫時不可用。這個時候,測試程式碼必須想方設法應對這種情況,以便提高工具和用例的健壯性,最常見的解決方法就是進行重試:當特定條件不滿足的時候,等待一段時間,然後再次嘗試,直到期望的條件滿足

邊界測試技術——健壯測試、最壞情況測試、健壯最壞情況測試

轉載 https://blog.csdn.net/dreamchasering/article/details/72614674 ==============================================   黑盒測試——邊界測試 邊界值分析是一種常用的黑盒測試方法,是對