net programming for microsoft windows 读书笔记

Network Programming for Microsoft Windows 《Network Programming for Microsoft Windows》,这本书是比较好的关于Windows网络编程书 立即下载
>

socket modes 和socket I/O models . 



socket modes (每一个socket对象自己所具备的特性 ):


As we mentioned, Windows sockets perform I/O operations in two socket operating modes: blocking and non-blocking . In blocking mode, Winsock calls that perform I/O—such as send and recv— wait until the operation is complete before they return to the program. In non-blocking mode, the Winsock functions return immediately.

   Once a socket is placed in non-blocking mode(by calling the ioctlsocket()), Winsock API calls that deal with sending and receiving data or connection management return immediately. In most cases, these calls fail with the error WSAEWOULDBLOCK , which means that the requested operation did not have time to complete during the call. For example, a call to recv returns WSAEWOULDBLOCK if no data is pending in the system's input buffer. Often additional calls to the same function are required until it encounters a successful return code.


socket I/O models(管理多个sockets的方法) :

   对于一个socket,我们可以使用blocking or non-blocking mode去处理.

   当有多个socket时怎么办?

  1 可以使用blocking socket加多线程的方法来处理,即每一个线程来处理一个socket的操作. 这样做的缺点是太多的线程浪费系统资源而且影响系统效率.

  2 如果使用non-blocking方式来处理, 但是随着sockets个数的增多, 程序要用不断循环的方法来调用函数直到他们成功, 程序变得无法管理.所以这个模式不存在.

  3 select模型.

  4 WSAAsyncSelect模型.

  5 WSAEventSelect模型.

  6 overlapped 模型.

  7 completion port


详解模型:

  1 blocking socket + 多线程.

     这种模式的好处是简单,容易实现. 坏处是因为要为每个socket创建一个或者两个线程来对它进行处理.所以非常浪费系统资源, 这里所说的系统资源是内存, 包括物理内存和虚拟内存. 每创建一个线程,系统要为线程在虚拟内存中保留1M的栈(这个操作使用了虚拟内存,每一个只有2GB的地址空间是属于用户的.), 而且还要为其中的一些虚拟内存分配一部分物理内存(计算机上的RAM).况且在运行时由于频繁的线程切换会使CPU很累.

  2 select模型

     We call it the select model because it centers on using the select function to manage I/O.

The select function can be used to determine if there is data on a socket and if a socket can be written to. The reason for having this function is to prevent your application from blocking on an I/O bound call such as send or recv when a socket is in a blocking mode and to prevent the WSAEWOULDBLOCK error when a socket is in a non-blocking mode. The select function blocks for I/O operations until the conditions specified as parameters are met.


int select(























































































int nfds,















































































































































































































































































































































































































































fd_set FAR * readfds,















































































































































































































































































































































































































































fd_set FAR * writefds,















































































































































































































































































































































































































































fd_set FAR * exceptfds,















































































































































































































































































































































































































































const struct timeval FAR * timeout















































































































































































































































































































































































































































);































































































































































































































































































































































































































































































































































































































































































































































































































































































书中说的不详细, 还有很多的疑问要在msdn中才能找到答案.






























































































































































































































































































































































































































































































































































































































































































































































































































































































比如在 readfds中的socket, 在满足以下三种情况时,认为可以操作。

1 当该socket上有数据可以被读取的时候。2 当该socket被关闭的时候。 3 当有连接请求要连接到该socket 时。

那么在该模型中并没有任何数据用来区别这三种情况,这三种情况中的任意一个发生时,都只是返回一个1而已。

区分的方法是: 如果在readfds中的socket处于listen状态但是没有调用accept时,那么这时肯定是有连接请求到达该socket,此时去accept的话,不会blocking.  如果在readfds中的socket已经是accept过的了,那么肯定是1或者2,那么怎么区别这两种情况呢,方法是直接调用recv函数,如果是1的情况,会成功收到数据。如果是2的情况,会返回一个错误值。


怎么用这个模式来处理多个链接呢?

用一个链表来保存接收到的socket, 用多线程,其中一个线程负责accept链接,得到socket后加入到链表中去.另外一个线程中while(true)一直调用select. 在select之前,每次都检查链表,如果有新socket加入,则把它也加到fd_read中去.


3 WSAAsyncSelect模型

   Winsock provides a useful asynchronous I/O model that allows an application to receive Windows message–based notification of network events on a socket.This is accomplished by calling the WSAAsyncSelect function after creating a socket.

   To use the WSAAsyncSelect model, your application must first create a window using the CreateWindow function and supply a window procedure (winproc ) support function for it. You can also use a dialog box with a dialog procedure instead of a window because dialog boxes are windows.

   Once you have set up the window infrastructure, you can begin creating sockets and turning on window message notification by calling the WSAAsyncSelect function, which is defined as

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


   The s parameter represents the socket we are interested in.

   The hWnd parameter is a window handle identifying the window or the dialog box that receives a message when a network event occurs.

    The wMsg parameter identifies the message to be received when a network event occurs.

    The last parameter, lEvent , represents a bitmask that specifies a combination of network events


WSAAsyncSelect(s, hwnd, WM_SOCKET, FD_CONNECT │ FD_READ │ FD_WRITE │ FD_CLOSE);















































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































当有connect,或fd_read,或fd_write,或fd_close这类的网络事件发生的时候, hwnd会收到一个WM_SOCKET事件, 而且在其中又可以根据lparam































































































































































































































































































































































































































































































































































































































































































































































































































































































来判断是哪一种事件.














































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































This allows our application to get connect, send, receive, and socket-closure network event notifications on socket s . It is impossible to register multiple events one at a time on the socket. Also note that once you turn on event notification on a socket, it remains on unless the socket is closed by a call to closesocket or the application changes the registered network event types by calling WSAAsyncSelect (again, on the socket). Setting the lEvent parameter to 0 effectively stops all network event notification on the socket.

   When your application calls WSAAsyncSelect on a socket, the socket mode is automatically changed from blocking to the non-blocking mode that we described previously(why? ).

   How to design the windows procedure?


  A window procedure is normally defined as

LRESULT CALLBACK WindowProc(































































































































































































































































































































































































































































































































































































































































































































































































































































































HWND hWnd,















































































































































































































































































































































































































































UINT uMsg,















































































































































































































































































































































































































































WPARAM wParam,















































































































































































































































































































































































































































 LPARAM lParam















































































































































































































































































































































































































































);

The hWnd parameter is a handle to the window that invoked the window procedure.

The uMsg parameter indicates which message needs to be processed. In your case, you will be looking for the message defined in the WSAAsyncSelect call.

The wParam parameter identifies the socket on which a network event has occurred. This is important if you have more than one socket assigned to this window procedure.

The lParam parameter contains two important pieces of information—the low word of lParam specifies the network event that has occurred, and the high word of lParam contains any error code.

When network event messages arrive at a window procedure, the application should first check the lParam high-word bits to determine whether a network error has occurred on the socket. There is a special macro, WSAGETSELECTERROR , that returns the value of the high-word bits error information. After the application has verified that no error occurred on the socket, the application should determine which network event type caused the Windows message to fire by reading the low-word bits of lParam . Another special macro, WSAGETSELECTEVENT , returns the value of the low-word portion of lParam .


One final detail worth noting is how applications should process FD_WRITE event notifications. FD_WRITE notifications are sent under only three conditions:

  • After a socket is first connected with connect or WSAConnect

  • After a socket is accepted with accept or WSAAccept

  • When a send, WSASend , sendto , or WSASendTo operation fails with WSAEWOULDBLOCK and buffer space becomes available

Therefore, an application should assume that sends are always possible on a socket starting from the first FD_WRITE message and lasting until a send , WSASend , sendto , or WSASendTo returns the socket error WSAEWOULDBLOCK . After such failure, another FD_WRITE message notifies the application that sends are once again possible.


The WSAAsyncSelect model offers many advantages; foremost is the capability to handle many connections simultaneously without much overhead, unlike the select model's requirement of setting up the fd_set structures. The disadvantages are having to use a window if your application requires no windows (such as a service or console application). Also, having a single window procedure to service all the events on thousands of socket handles can become a performance bottleneck (meaning this model doesn't scale very well).



4 the WSAEventSelect model

Winsock provides another useful asynchronous event notification I/O model that is similar to the WSAAsyncSelect model that allows an application to receive event-based notification of network events on one or more sockets. This model is similar to the WSAAsyncSelect model because your application receives and processes the same network events listed in Table 5-3 that the WSAAsyncSelect model uses. The major difference with this model is that network events are notified via an event object handle instead of a window procedure.


The event notification model requires your application to create an event object for each socket used by calling the WSACreateEvent function, which is defined as  WSAEVENT WSACreateEvent(void);


The WSACreateEvent function simply returns a manual reset event object handle. Once you have an event object handle, you have to associate it with a socket and register the network event types of interest


int WSAEventSelect(















































































































































































































































































































































































































































SOCKET s,















































































































































































































































































































































































































































WSAEVENT hEventObject,















































































































































































































































































































































































































































long lNetworkEvents















































































































































































































































































































































































































































);







































































The s parameter represents the socket of interest.

The hEventObject parameter represents the event object—obtained with WSACreateEvent— to associate with the socket.

The last parameter, lNetworkEvents , represents a bitmask that specifies a combination of network event types that the application is interested in.

The event created for WSAEventSelect has two operating states and two operating modes. The operating states are known as signaled and non-signaled . The operating modes are known as manual reset and auto reset .WSACreateEvent initially creates event handles in a non-signaled operating state with a manual reset operating mode.As network events trigger an event object associated with a socket, the operating state changes from non-signaled to signaled.

Because the event object is created in a manual reset mode, your application is responsible for changing the operating state from signaled to non-signaled after processing an I/O request. This can be accomplished by calling the WSAResetEvent function, which is defined as

BOOL WSAResetEvent(WSAEVENT hEvent);







































































The function takes an event handle as its only parameter and returns TRUE or FALSE based on the success or failure of the call.

When an application is finished with an event object, it should call the WSACloseEvent function to free the system resources used by an event handle. The WSACloseEvent function is defined as      BOOL WSACloseEvent(WSAEVENT hEvent);

This function also takes an event handle as its only parameter and returns TRUE if successful or FALSE if the call fails.


Once a socket is associated with an event object handle, the application can begin processing I/O by waiting for network events to trigger the operating state of the event object handle. The WSAWaitForMultipleEvents function is designed to wait on one or more event object handles and returns either when one or all of the specified handles are in the signaled state or when a specified timeout interval expires. WSAWaitForMultipleEvents is defined as

DWORD WSAWaitForMultipleEvents(







































































DWORD cEvents,







































































const WSAEVENT FAR * lphEvents,







































































BOOL fWaitAll,







































































DWORD dwTimeout,







































































BOOL fAlertable







































































);

The cEvents and lphEvents parameters define an array of WSAEVENT objects in which cEvents is the number of event objects in the array and lphEvents is a pointer to the array. WSAWaitForMultipleEvents can support only a maximum of WSA_MAXIMUM_WAIT_EVENTS objects, which is defined as 64. Therefore, this I/O model is capable of supporting only a maximum of 64 sockets at a time for each thread that makes the WSAWaitForMultipleEvents call.


If you need to have this model manage more than 64 sockets, you should create additional worker threads to wait on more event objects.


The fWaitAll parameter specifies how WSAWaitForMultipleEvents waits for objects in the event array.

If TRUE , the function returns when all event objects in the lphEvents array are signaled. If FALSE , the function returns when any one of the event objects is signaled. In the latter case, the return value indicates which event object caused the function to return. Typically, applications set this parameter to FALSE and service one socket event at a time.

The dwTimeout parameter specifies how long (in milliseconds) WSAWaitForMultipleEvents will wait for a network event to occur.

The final parameter, fAlertable , can be ignored when you're using the WSAEventSelect model and should be set to FALSE . It is intended for use in processing completion routines in the overlapped I/O model, which will be described later in this chapter.


Note that by servicing signaled events one at a time (by setting the fWaitAll parameter to FALSE ), it is possible to starve sockets toward the end of the event array.(这是WSAEventSelect一项缺点)


This is clearly undesirable. Once an event within the loop is signaled and handled, all events in the array should be checked to see if they are signaled as well. This can be accomplished by using WSAWaitForMultipleEvents with each individual event handle after the first signaled event and specifying a dwTimeOut of zero.


When WSAWaitForMultipleEvents receives network event notification of an event object, it returns a value indicating the event object that caused the function to return. As a result, your application can determine which network event type is available on a particular socket by referencing the signaled event in the event array and matching it with the socket associated with the event. When you reference the events in the event array, you should reference them using the return value of WSAWaitForMultipleEvents minus the predefined value WSA_WAIT_EVENT_0 .



For example:

Index = WSAWaitForMultipleEvents(...);







































































MyEvent = EventArray[Index - WSA_WAIT_EVENT_0];















































































































































Once you have the socket that caused the network event, you can determine which







































































network events are available by calling the WSAEnumNetworkEvents






































































function,







































































which is defined as

int WSAEnumNetworkEvents(







































































SOCKET s,







































































WSAEVENT hEventObject,







































































LPWSANETWORKEVENTS lpNetworkEvents







































































);


The s parameter represents the socket that caused the network event, and the hEventObject parameter is an optional parameter representing an event handle identifying an associated event object to be reset. Because our event object is in a signaled state, we can pass it in and it will be set to a non-signaled state. The hEventObject parameter is optional in case you wish to reset the event manually via the WSAResetEvent function. The final parameter, lpNetworkEvents , takes a pointer to a WSANETWORKEVENTS structure, which is used to retrieve network event types that occurred on the socket and any associated error codes. The WSANETWORKEVENTS structure is defined as

typedef struct _WSANETWORKEVENTS







































































{







































































long lNetworkEvents;







































































int iErrorCode[FD_MAX_EVENTS];







































































} WSANETWORKEVENTS, FAR * LPWSANETWORKEVENTS;

















































































































































注意:

More than one network event type can occur whenever an event is signaled. For example, a busy server application might receive FD_READ and FD_WRITE notification at the same time.


The iErrorCode parameter is an array of error codes associated with the events in lNetworkEvents . For each network event type, there is a special event index similar to the event type names—except for an additional “_BIT” string appended to the event name. For example, for the FD_READ event type, the index identifier for the iErrorCode array is named FD_READ_BIT . The following code fragment demonstrates this for an FD_READ event:

// Process FD_READ notification







































































if (NetworkEvents.lNetworkEvents & FD_READ)







































































{







































































if (NetworkEvents.iErrorCode[FD_READ_BIT] != 0)







































































{
















printf("FD_READ failed with error %d/n",

NetworkEvents.iErrorCode[FD_READ_BIT]);







































































}







































































}















































































































































After you process the events in the WSANETWORKEVENTS structure, your application should continue waiting for more network events on all of the available sockets. The following example demonstrates how to develop a server and manage event objects when using the WSAEventSelect I/O model. The code highlights the steps needed to develop a basic server application capable of managing one or more sockets at a time.


SOCKET SocketArray [WSA_MAXIMUM_WAIT_EVENTS];

WSAEVENT EventArray [WSA_MAXIMUM_WAIT_EVENTS], NewEvent;

SOCKADDR_IN InternetAddr;

SOCKET Accept, Listen;

DWORD EventTotal = 0;

DWORD Index, i;


// Set up a TCP socket for listening on port 5150 Listen = socket (PF_INET, SOCK_STREAM, 0);

InternetAddr.sin_family = AF_INET;

InternetAddr.sin_addr.s_addr = htonl(INADDR_ANY);

InternetAddr.sin_port = htons(5150);


bind(Listen, (PSOCKADDR) &InternetAddr, sizeof(InternetAddr));

NewEvent = WSACreateEvent();

WSAEventSelect(Listen, NewEvent, FD_ACCEPT │ FD_CLOSE);

listen(Listen, 5);


SocketArray[EventTotal] = Listen; EventArray[EventTotal] = NewEvent;

EventTotal++;

while(TRUE) {

// Wait for network events on all sockets

Index = WSAWaitForMultipleEvents(EventTotal, EventArray, FALSE, WSA_INFINITE, FALSE);

Index = Index - WSA_WAIT_EVENT_0;

// Iterate through all events to see if more than one is signaled

for(i=Index; i < EventTotal ;i++)

{

Index = WSAWaitForMultipleEvents(1, &EventArray[i], TRUE, 1000, FALSE);

if ((Index == WSA_WAIT_FAILED) ││ (Index == WSA_WAIT_TIMEOUT))

continue;

else

{ Index = i; WSAEnumNetworkEvents( SocketArray[Index], EventArray[Index], &NetworkEvents);

// Check for FD_ACCEPT messages

if (NetworkEvents.lNetworkEvents & FD_ACCEPT)

{

if (NetworkEvents.iErrorCode[FD_ACCEPT_BIT] != 0)

{

printf("FD_ACCEPT failed with error %d/n", NetworkEvents.iErrorCode[FD_ACCEPT_BIT]);

break; }

// Accept a new connection, and add it to the

// socket and event lists

Accept = accept( SocketArray[Index], NULL, NULL);

// We cannot process more than

// WSA_MAXIMUM_WAIT_EVENTS sockets, so close

// the accepted socket

if (EventTotal > WSA_MAXIMUM_WAIT_EVENTS)

{

printf("Too many connections");

closesocket(Accept);

break;

}

NewEvent = WSACreateEvent();

WSAEventSelect(Accept, NewEvent, FD_READ │ FD_WRITE │ FD_CLOSE);

EventArray[EventTotal] = NewEvent;

SocketArray[EventTotal] = Accept;

EventTotal++;

printf("Socket %d connected/n", Accept); }

// Process FD_READ notification

if (NetworkEvents.lNetworkEvents & FD_READ)

{

if (NetworkEvents.iErrorCode[FD_READ_BIT] != 0)

{ printf("FD_READ failed with error %d/n", NetworkEvents.iErrorCode[FD_READ_BIT]); break;

}

// Read data from the socket

recv(SocketArray[Index - WSA_WAIT_EVENT_0], buffer, sizeof(buffer), 0); }

// Process FD_WRITE notification

if (NetworkEvents.lNetworkEvents & FD_WRITE)

{

if (NetworkEvents.iErrorCode[FD_WRITE_BIT] != 0)

{ printf("FD_WRITE failed with error %d/n", NetworkEvents.iErrorCode[FD_WRITE_BIT]);

break;

}

send(SocketArray[Index - WSA_WAIT_EVENT_0], buffer, sizeof(buffer), 0); }

if (NetworkEvents.lNetworkEvents & FD_CLOSE)

{

if (NetworkEvents.iErrorCode[FD_CLOSE_BIT] != 0)

{

printf("FD_CLOSE failed with error %d/n", NetworkEvents.iErrorCode[FD_CLOSE_BIT]);

break;

}

closesocket(SocketArray[Index]); // Remove socket and associated event from // the Socket and Event arrays and decrement // EventTotal CompressArrays(EventArray, SocketArray, &EventTotal); } } } }

其实上例中的for循环可以不存在,只不过如果那样的话,如果第一个socket一直有event发生的话,那么数组中后边的socket总是很不到机会.















































































































































The WSAEventSelect






































































model offers several







































































advantages. It is conceptually simple and it does not require a windowed







































































environment. The only drawback is its limitation of waiting on only 64 events at







































































a time, which necessitates managing a thread pool when dealing with many







































































sockets. Also, because many threads are required to handle a large number of







































































socket connections, this model does not scale as well as the overlapped models







































































 


其实这几个模型看过以后,只要经常的回来看看这几个示例代码就可以了.

线程池技术?

The Overlapped Model:


The overlapped I/O model in Winsock offers applications better system performance than any of the I/O models explained so far.

The overlapped model's basic design allows your application to post one or more asynchronous I/O requests at a time using an overlapped data structure.

At a later point, the application can service the submitted requests after they have completed. This model is available on all Windows platforms except Windows CE. The model's overall design is based on the Windows overlapped I/O mechanisms available for performing I/O operations on devices using the ReadFile and WriteFile functions.

  To use the overlapped I/O model on a socket, you must first create a socket that has the overlapped flag set.

After you successfully create a socket and bind it to a local interface, overlapped I/O operations can commence by calling the Winsock functions listed below and specifying an optional WSAOVERLAPPED structure.

  • WSASend

  • WSASendTo

  • WSARecv

  • WSARecvFrom

  • WSAIoctl

  • WSARecvMsg

  • AcceptEx

  • ConnectEx

  • TransmitFile

  • TransmitPackets

  • DisconnectEx

  • WSANSPIoctl

  To use overlapped I/O, each function takes a WSAOVERLAPPED structure as a parameter.

When these functions are called with a WSAOVERLAPPED structure, they complete immediately—regardless of the socket's mode.

They rely on the WSAOVERLAPPED structure to manage the completion of an I/O request.

There are essentially two methods for managing the completion of an overlapped I/O request: your application can wait for event object notification or it can process completed requests through completion routines .

The first six functions in the list have another parameter in common: a WSAOVERLAPPED_COMPLETION_ROUTINE . This parameter is an optional pointer to a completion routine function that gets called when an overlapped request completes.


Event Notification

The event notification method of overlapped I/O requires associating Windows event objects with WSAOVERLAPPED

structures.

When I/O calls such as WSASend and WSARecv are made using a WSAOVERLAPPED structure, they return immediately.

Typically, you will find that these I/O calls fail with the return value SOCKET_ERROR and that WSAGetLastError reports a WSA_IO_PENDING error status.

This error status simply means that the I/O operation is in progress.

At a later time, your application will need to determine when an overlapped I/O request completes by waiting on the event object associated with the WSAOVERLAPPED structure.

The WSAOVERLAPPED structure provides the communication medium between the initiation of an overlapped I/O request and its subsequent completion, and is defined as

typedef struct WSAOVERLAPPED























{























DWORD Internal;























DWORD InternalHigh;























DWORD Offset;























DWORD OffsetHigh;























WSAEVENT hEvent;























} WSAOVERLAPPED, FAR * LPWSAOVERLAPPED;

The Internal, InternalHigh, Offset , and OffsetHigh fields are all used internally by the system and an application should not manipulate or directly use them. The hEvent field, on the other hand, allows an application to associate an event object handle with this operation.

When an overlapped I/O request finally completes, your application is responsible for retrieving the overlapped results. In the event notification method, Winsock will change the event-signaling state of an event object that is associated with a WSAOVERLAPPED structure from non-signaled to signaled when an overlapped request finally completes. Because an event object is assigned to the WSAOVERLAPPED structure, you can easily determine when an overlapped I/O call completes by calling the WSAWaitForMultipleEvents function

Once you determine which overlapped request has completed, you need to determine the success or failure of the overlapped call by calling WSAGetOverlappedResult , which is defined as

BOOL WSAGetOverlappedResult(























SOCKET s,























LPWSAOVERLAPPED lpOverlapped,























LPDWORD lpcbTransfer,























BOOL fWait,























LPDWORD lpdwFlags























);

The s parameter identifies the socket that was specified when the overlapped operation was started.

The lpOverlapped parameter is a pointer to the WSAOVERLAPPED structure that was specified when the overlapped operation was started.

The lpcbTransfer parameter is a pointer to a DWORD variable that receives the number of bytes that were actually transferred by an overlapped send or receive operation.

The fWait parameter determines whether the function should wait for a pending overlapped operation to complete.

If fWait is TRUE , the function does not return until the operation has been completed. If fWait is FALSE and the operation is still pending, WSAGetOverlappedResult returns FALSE with the error WSA_IO_INCOMPLETE .Because in our case we waited on a signaled event for overlapped completion, this parameter has no effect(这个参数在其它的情况下有用,但是在我们这个model里用不上,因).






the completion port model:


真面目







































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































































 做个比喻:

   socket mode:

  socket s, s有两种类型,一个是blocking的,一个是non-blocking的。 如果是个人的话,那么这个人有两种, 一种是很执着的人(blocking),你派他去菜市场买菜,没卖菜的他就坐那等,一直等到买到菜。但是家里要做饭,都得等着他。另一种是会变通的人(non-blocking), 他去看到没有菜卖就会马上回家来,如果你想再让他买,就再让他去,一直到买到为止。


socket I/O models:

  比如你是个大家庭,有很多人,即你有很多个socket. 你需要一个方法来管理这些s.

1 blocking + 多线程

  你把这些S都设置成blocking mode的,每个S都用一个线程管理。


2 使用select模型:



如何写一个高性能的可应对多个连接的c/s程序:


The only I/O model that provides true scalability on Windows NT platforms is overlapped I/O using completion ports for notification . In Chapter 5, we covered the various methods of socket I/O and explained that for a large number of connections, completion ports offer the greatest flexibility and ease of implementation. Mechanisms like WSAAsyncSelect and select are provided for easier porting from Windows 3.1 and UNIX, respectively, but are not designed to scale. The event-based models are not scalable because of the operating system limit of simultaneous wait events.



一个服务器可以接收多少个并发连接?

同一个进程中能有两个bind到同一个数据的socket吗.

什么是集群技术?



难以理解的知识点 :

一:

 int                  ClientAddrLen = sizeof(SOCKADDR_IN);

.........

.........

..........

 if ((NewConnection = accept(ListeningSocket, (SOCKADDR *) &ClientAddr,&ClientAddrLen)) == INVALID_SOCKET)
   {
      printf("accept failed with error %d/n", WSAGetLastError());//WSAEFault
      closesocket(ListeningSocket);
      WSACleanup();
      return;
   }

如果把第一行改为:   int                  ClientAddrLen = sizeof(SOCKADDR_IN);

则accept()函数会一直返回invalid_socket. 并且调用WSAGetlastError()会返回0.一直不知道这个0是什么意思. 在网上看到其它人说他们的值是10014.



二

什么是spi?比如wsprecv(). 他们是比winsock API更底层一些的 service provider interface提供的,普通的api, 如send,由ws2_32.dll中来,

而spi api, 如wsprecv,则由mswsock.dll中来.


WINDOWS下的防火墙技术都被研究得比较透了  
  目前认为比较完善的方法就是NDIS  
  简单一点的就是SPI  
   
  我本来想在毕业的时候做毕业设计做个SPI防火墙,现在觉得技术难度有点低了,准备到时候做个NDIS的,完善一点的  
   
  SPI的基本原理其实和NDIS都差不多,主要体现一个思想:分层!  
  其实仔细想想,整个WINDOWS偶觉得都是分层式结构,假如我们用MFC写程序  
  那么MFC调用API,API又调用更低级的API,然后转换成相应的IRQ到内核里的驱动。。。。。  
   
  上面的话题扯得比较远了,平时我们调用WINSOCK   API是这样的  
  winsock   api->SPI->驱动->网卡  
  其中SPI可以由很多层构成,我们也可以插入自己的层,只要符合层与层之间的接口就行了,这个接口就是WSPStarup函数,SPI的每一层都需要为上一层提供WSPStarup函数传递自己的30个SPI函数的指针,同时调用下一层的WSPStarup函数来得到下一层SPI的30个函数指针,如果你不需要做任何事,只想中转一下,那么就可以直接在自己的函数里调用下一层SPI的相应函数提供给上一层SPI,如果想实现防火墙功能,你就在这些函数里实现自己的网络封包。  
   
  你自己写的SPI是一个DLL,也有DllMain函数,你要在DLL里把自己的WSPStartup函数导出以便上一层SPI程序调用,主要注意这个函数的最后一个参数,在WSPStartup里把你得到的下一层SPI函数指针指向你自己实现的函数就可以了  
   
  比如  
  int   WSPStartup   (  
      WORD                                           wVersionRequested,                                
      LPWSPDATAW                               lpWSPData,                                    
      LPWSAPROTOCOL_INFOW             lpProtocolInfo,        
      WSPUPCALLTABLE                       UpcallTable,                        
      LPWSPPROC_TABLE                     lpProcTable        
  {  
      .............  
    lpProcTable->lpWSPBind=WSPBind(....);//这样就把下一层SPI函数指针指向了自己的的WSPBind函数  
  }  
   
  上面就当最近一段时间研究SPI防火墙的一点总结  
  个人看法,分层结构是个很不错的构思,TCP/IP协议也是分层的,分层结构可以不要关注别的层之间的细节,只要专注于自己层然后按照规定提供相应的上下接口就OK了,值得我们自己在程序中借鉴!很多时候,思想更重要  



SAP ABAP VL09 BAPI VL 216 ls_batch_item-fact_unit_denom = ls_lips_split-umvkn. "销售数量转换为 SKU 的值(分母)ls_batch_item-fact_unit_nom = ls_lips_split-umvkz. "销售数量转换成SKU的分子(因子)ls_batch_item-sales_unit_iso = ls_lips_split-meins. "被拆分DN基本单位。 阅读详情

相关推荐

计算机组成原理(二)—— 数据的表示与运算

本章目录引言一、数制与编码1.1 进位计数制1.1.1 进制及转换1.1.2 真值、机器数1.2 BCD码1.3 ASCII 码1.4 校验码1.4.1 奇偶校验码1.4.2 海明码1.4.3 CRC循环冗余码二、定点数的表示和运算2.1 定点数的表示2.1.1 无符号2.1.2 有符号(原码、反码、补码、移码)2.2 定点数的运算2.2.1 移位运算2.2.2 加减运算(溢出判断)2.2.3 乘法运算2.2.4 除法运算2.3 强制类型转换2.4 数据的存储和排列三、浮点数的表示和运算3.1 浮点数的表示

S mile0804的博客 7473

Network Programming for Windows读书笔记2

    connect函数和WSAConnect函数    最后一步就是连接.这是通过调用connect 函数或WSAConnect函数来完成的.我们先来看看该函数的Winsock1版本,其定义如下:    int connect(            SOCKET s,             const struct sockaddr FAR* name,        

orichisonic的专栏 937

深度学习模型设计的方法和技巧

设计神经网络模型是一个迭代的过程,需要不断试验和调整各个组成部分,以达到最佳性能。同时,遵循良好的工程实践,如模块化设计、版本控制、文档记录等,也是成功的关键。

xw555666的博客 4027

[翻译]-Programming Microsoft Windows CE .NET, Third Edition-目录

Programming Microsoft Windows CE .NET, Third Editionby Douglas Boling  ISBN:0735618844Microsoft Press © 2003 (1224 pages)作者对如何把Windows、嵌入式程序设计经验应用到Windows CE.NET环境里做了娴熟的示范。这这个环境里,可以为支持Windows的Pocket P

tellmenow的专栏 8060

什么是以太网链路聚合

以太网链路聚合技术通过将多个物理端口捆绑成逻辑端口,可显著提升网络性能。该技术能增加总带宽(各链路带宽之和)、提高可靠性(故障秒级切换)并实现智能负载分担。主要分为手工模式和基于LACP协议的动态模式,后者能检测链路故障更可靠。配置时需确保接口参数一致、模式匹配,适用于核心交换、服务器接入等场景。华为设备通过创建Eth-Trunk接口、指定LACP模式并添加成员接口即可完成部署。这项成熟技术能以低成本解决带宽瓶颈和可靠性问题,是构建高速稳定网络的关键方案。

lai_2020的博客 674

ubuntu20.04 终端安装claude

【代码】ubuntu20.04 终端安装claude。

hongliyu_lvliyu的博客 2596

Network Programming for Microsoft Windows 2nd Edition

Network Programming for Microsoft Windows 2nd EditionPublisher: Microsoft Press | 2nd edition (February 13, 2002) | 608 pages | ISBN: 0735615799 | Rar Size : 1.7 MB | CHM Winsock appl

Linhanshi Blog 2012

NLP DAY1: 文本数据读取

txt 文本数据的读写CSV 及 Excel 文本数据的读写更多的 DataFrame 操作数据规模太大怎么办相信通过本次实验的学习,同学们可以游刃有余地面对各种数据文件了。在接下来的实验中,我们将开始真正地开启自然语言处理之旅,开始认识并熟悉一些常见的针对文本本身的预处理操作。

feifeikon的博客 1060

[ASP.NET教程] Microsoft Robotics Studio入门系列

原文标题:Getting Started with Microsoft Robotics Studio Microsoft Robotics Studio: An Introduction The Microsoft Robotics Studio is a Windows-based environment for academic,http://www.km

慕斯筱婕 719

RSA 2048/4096 签名校验算法

RSA算法是一种非对称密码算法,所谓非对称,就是指该算法需要一对密钥,使用其中一个加密,则需要用另一个才能解密。 RSA是目前最有影响力和最常用的公钥加密算法,它能够抵抗到目前为止已知的绝大多数密码攻击,已被ISO推荐为公钥数据加密标准。 今天只有短的RSA钥匙才可能被强力方式解破。到2008年为止,世界上还没有任何可靠的攻击RSA算法的方式。只要其钥匙的长度足够长,用RSA加密的信息实际上是不能...

qq_38769551的博客 9500

latex写论文(TeXstudio工具)

目录前言IEEE模板模板免费分享参考文献写作方法我的.tex文件代码 前言 学校老师要求我们以IEEE顶级会议格式与标准写报告,于是过程虽然麻烦点,但是效果还是不错了,下面先展示一下自己写完的效果。 IEEE模板 我是在 Overleaf 上注册了个账号下载了模板,里面有各种会议论文的写作模板,这个注册还挺麻烦,要外网注册,国内邮箱都不行。进行后点菜单,菜单里有下载源码。 https://cn.overleaf.com/project/5fe5b082dff088649fc67106 模板免费分享 已

小样yx的博客 6752

Professional WPF Programming: .NET Development with the Windows Presentation Foundation

版权声明:原创作品,允许转载,转载时请务必以超链接形式标明文章原始出版、作者信息和本声明。否则将追究法律责任。http://blog.csdn.net/topmvp - topmvpProfessional WPF Programming If you want to learn how to build killer user interfaces for Windows and the w

TopMVP 503

【学长笔记】关于车牌识别的CCPD数据集按比例划分

本文介绍了一个用于CCPD车牌数据集划分的Python脚本,主要功能包括:1) 将数据集按比例划分为训练集、验证集和测试集;2) 支持图像与标签文件校验;3) 可自定义划分比例和样本数量限制;4) 自动生成标准目录结构。脚本使用随机种子确保可重复性,并通过tqdm显示进度条。处理后数据可直接用于YOLO等目标检测模型的训练与评估,建议在预处理完成后立即执行划分以避免数据泄露。文章还提供了相关技术博客的参考链接。

apple_53308981的博客 1478

电子书下载:Programming Windows Identity Foundation

Book DescriptionGet hands-on guidance designed to help you put the newest .NET Framework component- Windows Identity Foundation, the identity and access logic for all on-premises and cloud develo...

weixin_30545285的博客 114

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Devexpress16.2.6破解工具

Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具Devexpress16.2.6破解工具

[翻译]-Programming MS WinCE (3rd 版)--前言--Windows CE开发工具

Windows CE开发工具本书假设读者了解C和熟悉微软Windows,在XP下用微软嵌入式Visual C++开发过本地程序。为了编译书中的例子程序,需要微软嵌入式Visual C++ 4.0,这可以在附书光盘中找到。需要相关的适合Windows CE设备的SDK,用于你的目标设备。每个例子已经有一个预先定义好的工程设置,但你也可以选择从头创建一个工程。对大多数例子来说,简单创建一个普通WCE应

tellmenow的专栏 4760

NTscan扫描工具

ntscan是一个扫描器,可以扫描没有密码和弱密码的共享,先到配置文件中填写猜测的用户名和密码,扫描过程中右侧出现的是扫描日志。

[翻译]Programming Windows Phone 7 Series简介以及开发环境搭建

前言 几个星期以前发邮件问Charles 是否能翻译他的书《Programming Windows Phone 7 Series》,可能他太忙,也没有得到回复,我试着翻译一下,作为学习之用,如果以后有版权问题,我会把文章删掉。翻译以意译为主,我尽力保留原意,由 于个人能力问题,不能保证完全表达原意,欢迎阅读原著和帮忙挑错。同时我会在文章中补充一些截图,以及表达我对Windows Phone,Win...

weixin_30633507的博客 215

汉书HE8,好用的汇编代码编写工具

汉书HE8,好用的汇编代码编写工具早期编写汇编代码所用功能强大

[翻译]-Programming MS WinCE (3rd 版)封底

封底用这本广受业界推崇的Windows CE.NET参考书,为最新的智能移动设备设计整洁、高性能的应用程序。在第3版里,基本内容已经根据Windows CE.NET 4.2和微软.NET CF做了更新。作者Douglas Boling对如何把Windows、嵌入式程序设计经验应用到Windows CE.NET环境里做了娴熟的示范。在这个环境里,可以为支持Windows的Pocket PC、Smar

tellmenow的专栏 3928

Windows Forms 2.0 Programming (2nd Edition) (Microsoft .Net Development Series)

by Chris Sells, Michael Weinhardt Paperback: 1296 pages Publisher: Addison-Wesley Profes

Linhanshi Blog 1545

Programming Microsoft Windows Ce .Net, Third Edition(内置源码)

作者: Douglas BolingISBN: 9780735618848 页数: 1224定价: USD 59.99出版社: Microsoft Press装帧: Paperback出版年: 2003-06-25语言:英文下载:http://www.ziddu.com/download/7109088/Program

电子书下载 377

c programming language_重磅!C、C++不得宠,微软正在开发新的编程语言?

76 年迭代与更新,编程语言界,谁主沉浮?在六百多种编程语言中,对于开发者而言,其主观印象中或只有几种主流的编程语言,如 Java、C、C++、C#、新贵 Python 等,而之所以它们能够成为主流,软件开发生态必是其中不可或缺的一个重要部分。以最通用的编程语言之一 C# 为例,作为类型安全、面向对象的编程语言,C# 可以良好地运行在 .NET 框架运行时环境中。随着其优势的逐渐显现,微软作为背后...

weixin_39851914的博客 223

Programming for the New Platform

 Programming for the New Platform基于新平台的程序设计Jeffrey RichterTranslator: Bin Yang (AREC PINK TEAM)在过去的这些年里,我一直关注微软.NET通用语言运行(Common Language Runtime)平台。我认为,大多数新的开发将集中到这个平台上来,因为它使得程序开发更容易、更便

Flyincloud的专栏 931

Windows编程革命简史

源文:A Brief History of Windows Programming Revolutions (Ron Burk) 首先,是 Windows API 和 DLL Hell。(译注:DLL Hell——DLL灾难,就是微软的DLL升级时因为不同版本可能造成应用程序无法运行的灾难,首当其冲的是COM编程,相信大家都知道某些木马或是病毒更改了一些系统的DLL可以导致整个Windows

Miracles happen every day. 2440

Microsoft Robotics Studio入门系列

原文标题:Getting Started with Microsoft Robotics Studio   Microsoft Robotics Studio: An Introduction The Microsoft Robotics Studio is a Windows-based environment for academic, hobbyist, and c

1066

An Introduction to Programming Using Microsoft Visual C# 2005 Express Edition

August 2004 Download the Code.msi sample file.Note   This article assumes youre a hobbyist, student, or programming-minded individual interested in exploring the C# programming language and the .

阿宝 2993
上一篇: TCP/IP第一卷读书笔记
下一篇: oracle学习笔记
keepdoingit
博客等级 码龄17年 27粉丝 63原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值