WinSock Tips

1.使用同步SOCKET就用select模型,并且最好带一个超时
2.Assuming 0 is an invalid socket handle value. Uncontrollably lame.
3
the proper closure of a connected stream socket involves:

call shutdown() with the how equal to 1
loop on recv() until it returns 0 or fails with any error
call closesocket()

Call WSACleanup()


4.不要使用strlen()来获取host ip的长度


5
Assuming that a UDP datagram of any length may be sent. Criminally lame.


Reason: Various networks all have their limitations on maximum transmission unit (MTU). As a result, fragmentation will 


occur, and this increases the likelihood of a corrupted datagram (more pieces to lose or corrupt). Also, the TCP/IP service 


providers at the receiving end may not be capable of re-assembling a large, fragmented datagram.


Alternative: Check for the maximum datagram size with the SO_MAX_MSG_SIZE socket option, and don’t send anything larger. 


Better yet, be even more conservative. A max of 8K is a good rule-of-thumb.
不要发送太长的数据,不然会因MTU分块,8K刚好


6.
Expecting errors when UDP datagrams are dropped by the sender, receiver, or any router along the way. Seeping lameness from 


every crack and crevice.


Reason: UDP is unreliable. TCP/IP stacks don’t have to tell you when they throw your datagrams away (a sender or receiver 


may do this when they don’t have buffer space available, and a receiver will do it if they cannot reassemble a large 


fragmented datagram.


Alternative: Expect to lose datagrams, and deal. Implement reliability in your application protocol, if you need it (or use 


TCP, if your application allows it).


**************************************
模型选择
1.尽量避免用select()
2.少量连接用WSAAsyncSelect或WSAEventSelect
3.大量连接用Overlapped IO/Completion Port


Silly Window Syndrome:
发送端send太快,对方接受太慢,以至于接收方一但有N个“滑动窗口可用时”,发送方立马发送N个字节的数据,
这会使Overhead非常大,对应策略是用delayed ACK


Winsock is not required to give you all the data it has queued on a socket even if your recv() call gave Winsock enough 


buffer space. It may require several calls to get all the data queued on a socket.


除非需要考虑实时性,否则不要关闭Nagle算法


对于TCP字节流,可用2种处理方法:
1.在发送数据前加2个或多个字节的“长度”


有效使用TCP:
数据结构要处理好(内存对齐问题)


WSAData不用初始化,WSAStartup() fills this structure in for you.
2.在数据之后加“断开标示”,如HTTP的 \r\n


用WINSOCK编写的程序可以和UNIX系统通信

 Is it possible to close the connection “abnormally”?
The simplest way is to call shutdown() with the how parameter set to SD_BOTH (“both directions”), optionally followed by a 
closesocket() call. Another method is to set the SO_LINGER flag to 0 with the setsockopt() call before you call closesocket
(). This causes a TCP connection reset. (That is, a TCP packet goes out with the RST flag set, forcing the remote stack to 

drop the connection immediately.)


What is UDP good for?

From the above discussion, UDP looks pretty useless, right? Well, it does have a few advantages over reliable protocols like TCP:

  1. UDP is a slimmer protocol: its protocol header is fixed at 8 bytes, whereas TCP’s is 20 bytes at minimum and can be more.

  2. UDP has no congestion control and no data coalescing. This eliminates the delays caused by the delayed ACK and Nagle algorithms. (This is also a disadvantage in many situations, of course.)

  3. There is less code in the UDP section of the stack than the TCP section. This means that there is less latency between a packet arriving at the network card and being delivered to the application.

  4. Only UDP packets can be broadcast or multicast.

This makes UDP good for applications where timeliness and control is more important than reliability. Also, some applications are inherently tolerant of UDP problems. You have likely experienced blips, skips and stutters in streaming media programs: these are due to lost, corrupted or duplicated UDP frames.

Be careful not to let UDP’s advantages blind you to its bad points: too many application writers have started with UDP, and then later been forced to add reliability features. When considering UDP, ask yourself whether it would be better to use TCP from the start than to try to reinvent it. Note that you can’t completely reinvent TCP from the Winsock layer. There are some features of TCP like path MTU discovery that require low-level access to the OS’s networking layers. Other features of TCP are possible to duplicate over UDP, but difficult to get right. Keep in mind, TCP/IP was created in 1981, and the particular implementation you are using probably has code in it going back nearly that far. A whole lot of effort has gone into tuning this protocol suite for reliability and performance. You will be throwing away those decades of experience in trying to reinvent TCP or invent something better.

If you need a balance between UDP and TCP, you might investigate RTP (RFC 1889) and SCTP (RFC 2960). RTP is a higher level prototocol that usually runs over UDP and adds packet sequence numbers, as well as other features. SCTP runs directly on top of IP like TCP and UDP; it is a reliable protocol like TCP, but is datagram oriented like UDP.


5.不要在多个线程中对同一个socket调用send

Instead of multiple threads accessing a single socket, you may want to consider setting up a pair of network I/O queues. Then, give one thread sole ownership of the socket: this thread sends data from one I/O queue and enqueues received data on the other. Then other threads can access the queues (with suitable synchronization).

Applications that use some kind of non-synchronous socket typically have some I/O queue already. Of particular interest in this case is overlapped I/O or I/O completion ports, because these I/O strategies are also thread-friendly. You can tell Winsock about several OVERLAPPED blocks, and Winsock will finish sending one before it moves on to the next. This means you can keep a chain of these OVERLAPPED blocks, each perhaps added to the chain by a different thread. Each thread can also call WSASend() on the block they added, making your main loop simpler.



6.If two threads in an application call recv() on a socket,will they each get the same data?

No. Winsock does not duplicate data among threads.



Is there any way for two threads to be notified when something happens on a socket?

No.

If two threads call WSAAsyncSelect() on a single socket, only the thread that made the last call to WSAAsyncSelect() will receive further notification messages.

If two threads call WSAEventSelect() on a socket, only the event object used in the last call will be signaled when an event occurs on that socket.

You can’t trick Winsock by calling WSAAsyncSelect() on a socket in one thread and WSAEventSelect() on that same socket in another thread. These calls are mutually exclusive for any single socket.

You also cannot reliably call select() on a single socket from two threads and get the same notifications in each, because one thread could clear or cause an event, which would change the events that the other thread sees.

As recommended above, you should give sole ownership of a socket to a single thread, then have it communicate with the other threads.


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值