Windows网络编程经验小结

转自:CSDN网友的强贴,其ID:gdy119 (夜风微凉)

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;

}

Windows网络编程经验小结,布布扣,bubuko.com

时间: 2024-10-27 11:25:37

Windows网络编程经验小结的相关文章

网络编程学习小结

几种网络编程方式: ISAPI.CGI.WinInet.Winsock 它们之间的差别: 1)  ISAPI主要是开发基于浏览器client与server端程序.效率比CGI方式高,并且也扩展了CGI没有的一些功能.(基于TCP/IP模型中的应用层) 2)  CGI主要是开发基于浏览器client与server端程序.(基于TCP/IP模型中的应用层) 3)  WinInet主要是开发client程序.(基于TCP/IP模型中的应用层) 4)  Winsock主要是基于socket来开发clie

Socket网络编程--epoll小结

以前使用的用于I/O多路复用为了方便就使用select函数,但select这个函数是有缺陷的.因为它所支持的并发连接数是有限的(一般小于1024),因为用户处理的数组是使用硬编码的.这个最大值为FD_SETSIZE,这是在<sys/select.h>中的一个常量,它说明了最大的描述符数.但是对于大多数应用程序而言,这个数是够用的,而且有可能还是太大的,多数应用程序只使用3~10个描述符.而如今的网络服务器小小的都有几万的连接,虽然可以使用多线程多进程(也就有N*1024个).但是这样处理起来既

Windows网络编程

第一章 序言 我写这个专题的目的,一方面是为了通过对网络编程再一次系统的总结,提高自己的网络编程水平,特别是Windows下的网络编程水平.同一时候,我也希望,能为众多初学网络编程的人提供一点帮助,由于我開始学习网络编程的时候,能找到的资料就非常少.当然,花钱能够买到翻译版本号的书:) 首先向大家推荐一本非常好的參考书,Network Programming for Microsoft Windows 2nd, 初学网络编程的时候我还不知道有这样一本好书,仅仅是上各大论坛把能找到的网络编程方面的

Windows网络编程 2 【转】

Windows网络编程使用winsock.Winsock是一个基于Socket模型的API,在Windows系统中广泛使用.使用Winsock进行网络编程需要包含头文件Winsock2.h,需要使用库ws2_32.lib,包含方法:可以使用语句来告诉编译器连接该库#pragma comment(lib, “ws2_32.lib”);如果使用VS,可以通过“项目” --> “XX属性”--> “连接器”-->“输入”--> “附加依赖项”添加ws2_32.lib. (XX为当前工程名

windows网络编程的一些理论

参考自<VC++深入详解> 这是我在看书时记录下来的东西. 注:下面的Socket其实都应该是socket 第14章网络编程 Socket是连接应用程序与网络驱动程序的桥梁,Socket在应用程序中创建,通过绑定与驱动程序建立关系. 此后,应用程序给Socket的数据,由Socket交给驱动程序向网络上发送出去. 计算机从网络上收到与该Socket绑定的IP地址和端口号相关的数据后,由驱动程序交给Socket,应用程序便可从该Socket中提取接收到的数据. 14.1 计算机网络基本知识. 1

72&gt;&gt;Windows 网络编程

1 网络编程 API 2 3 4 int WSAStartup( WORD wVersionRequested, LPWSADATA lpWSAData ); lpWSAData 是一个返回值:成功返回 0,失败返回 -1,错误代码 WSASYSNOTREADY 表示基础网络子系统没有准备好网络通行,WSAVERNOTSUPPORTED 表示 Socket 版本不支持,WSAEINPROGRESS 表示一个阻塞的 Sockets 操作在进程中,WSAEPROCLIM 表示 Sockets 支持的

windows 网络编程[转]

利用winsock编写网络应用程序服务端的步骤简述如下WSAStartup 初始化网络编程库 socket 创建套接字 bind 指定地址.端口,绑定套接字 listen 进入监听状态 accept 等待接收新连接 send/recv 收发数据 closesocket 关键套接字 WSAStartup 释放对动态库的使用 下面详细介绍各API 1. Winsock初始化 调用int WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData

Windows 网络编程(2)--重叠I/0模型

5).重叠I/O模式(overlapped) 常用函素: 1.WSASocket : 创建套接字 2.TCP WSASend WSARecv 3.UDP: WSASendTo WSARecvFrom 4.AccepEx (Mswsock.lib库导出) WSAIoctl 5.数据类型 WSAOVERLAPPED (wsaoverlapped) 函数: WSAGetOverlappedResult 使用: 缓冲区对象 typedef struct _BUFFER_OBJ { OVERLAPPED

TCP网络编程学习小结

TCP协议是TCP/IP协议族中的一个十分重要的名字(看到TCP/IP这个名字就知道TCP有多重要了),同时也是一个十分复杂的协议,在使用这个协议的时候可能会带来很多问题,这使得使用的程序员会十分头大.如果想了解TCP协议的细节,可以参考<TCP/IP详解1:协议>.闲话不多说,我们进入正题: 一.报文头 首先我们来看一下TCP协议的报文头: TCP是传输层协议,其报文头并不包含TP地址,IP地址会在IP层添加,当然,IP层处于TCP的下层,IP层的报文内容就是TCP报文. TCP/IP协议网