惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

Google DeepMind News
Google DeepMind News
N
Netflix TechBlog - Medium
The Register - Security
The Register - Security
C
Cybersecurity and Infrastructure Security Agency CISA
H
Hackread – Cybersecurity News, Data Breaches, AI and More
The Hacker News
The Hacker News
P
Proofpoint News Feed
Project Zero
Project Zero
The GitHub Blog
The GitHub Blog
The Last Watchdog
The Last Watchdog
F
Fortinet All Blogs
S
Schneier on Security
Help Net Security
Help Net Security
Security Archives - TechRepublic
Security Archives - TechRepublic
C
Check Point Blog
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
P
Proofpoint News Feed
I
InfoQ
T
The Blog of Author Tim Ferriss
Cisco Talos Blog
Cisco Talos Blog
Stack Overflow Blog
Stack Overflow Blog
T
Troy Hunt's Blog
人人都是产品经理
人人都是产品经理
T
Threatpost
www.infosecurity-magazine.com
www.infosecurity-magazine.com
C
Cyber Attacks, Cyber Crime and Cyber Security
雷峰网
雷峰网
cs.AI updates on arXiv.org
cs.AI updates on arXiv.org
Threat Intelligence Blog | Flashpoint
Threat Intelligence Blog | Flashpoint
爱范儿
爱范儿
Forbes - Security
Forbes - Security
Vercel News
Vercel News
S
Security Affairs
美团技术团队
P
Privacy & Cybersecurity Law Blog
N
News and Events Feed by Topic
Cyberwarzone
Cyberwarzone
Recent Commits to openclaw:main
Recent Commits to openclaw:main
Jina AI
Jina AI
Spread Privacy
Spread Privacy
Attack and Defense Labs
Attack and Defense Labs
IT之家
IT之家
U
Unit 42
Recorded Future
Recorded Future
W
WeLiveSecurity
PCI Perspectives
PCI Perspectives
P
Palo Alto Networks Blog
H
Hacker News: Front Page
S
Security @ Cisco Blogs
博客园 - 【当耐特】

博客园 - sashow

c++知识点--extern "C"的作用 - sashow - 博客园 粘贴一点有用的东西留存-- Control 类的事件顺序 开始→运行→输入命令集锦 c#的ThreadPool使用笔记(四)--实例:端口扫描程序 c#的ThreadPool使用笔记(三) c# 中Label 标签和.resx 文件中的换行问题 - sashow 计算某天是星期几的算法 find 和 grep 命令 - sashow Sql Server 中由数字转换为指定长度的字符串 sql server 2005 使用问题总结 [转]解决无法显示所有文件和文件夹,无法显示隐藏文件和文件夹 FileStream进行Read() 操作后文件指针指向当前位置 用回车键模拟TAB键的方法 c#的ThreadPool使用笔记(二) c#的ThreadPool使用笔记(一) 人民币大小写转换(C#) 放弃还是继续? 随便写点东西 [转贴]Informix SQL函数的详细用法
[分享] C# 中 Socket 进行数据接收的一点心得
sashow · 2008-04-15 · via 博客园 - sashow

在利用Socket 进行Tcp/Ip 编程的时候,免不了要进行数据的发送和接收,而数据的接收,用得最多的就是 Socket 的同步函数 Receive (或它的重载):

public int Receive (
    
byte[] buffer,
    
int offset,
    
int size,
    SocketFlags socketFlags
)

或者是异步函数 BeginReceive( 或它的重载):

public IAsyncResult BeginReceive (
    
byte[] buffer,
    
int offset,
    
int size,
    SocketFlags socketFlags,
    AsyncCallback callback,
    Object state
)

这里,我想说的是异步函数 BeginReceive()。

使用了异步函数BeginReceive(),伴随而来的就是要定义一个

AsyncCallback 类型的函数(如下面取名为ReceiveEnd的函数),在这个函数里面,我们最少要做的事情时调用 Socket 的 EndReceive() 函数。

protected void ReceiveEnd(IAsyncResult ar){
    Socket client 
= (Socket)ar.AsyncState;
    
int recvLen = client.EndReceive(ar);

    
if ( recvLen > 0){        /* 接收到了数据 */
        client.BeginReceive(buffer, 
0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveEnd), client);  /* 继续接收数据*/
    }

    
else{
        client.Close();     
    }

}

在Msdn 2005 的 ms-help://MS.MSDNQTR.v80.chs/MS.MSDN.v80/MS.NETDEVFX.v20.chs/cpref10/html/M_System_Net_Sockets_Socket_BeginReceive_3_2b547d4d.htm
基本上就是上面这个意思,但是现在问题来了:
如果我定义的 buffer 的长度为 10,但我发送的数据长度为12或者8,那么,函数就不会走到 else 的部分,而是阻塞在函数中的 BeginReceive()调用。开始,我的想法是在发送的数据尾部增加一个特殊的字符(串),然后,在接收的时候判断有没有接收到这个字符(串)(我查阅了网上一些资料,还真有一些是这么做的!),但是,这种做法始终有一个毛病:那就是发送端发送的正文里面不能含有这个字符(串),否则,正文中在这个字符(串)后面的正文就会被丢掉。
所以,我想还是只能通过 Socket 自己的内部机制来实行,也就是想办法使程序走到 else 的部分。
经过测试:
在客户端发送完数据后,使用 Socket.Shutdown(SocketShutdown.Send ),或者Socket.Close()可以使程序走到 else 部分。
但是,这也带来了一个问题:
如果我定义的buffer 的长度为10,我发送的数据的长度也刚好为10,那么,函数在客户端不用Shutdown或Close的情况下,就已经走到了else 部分,然后 服务端的Socket 被 Close,等到客户端使用 Shutdown()或Close() 的时候,服务端的连接 Socket 已经是不可用了,而这个时候调用 EndReceive 操作,会引发异常。
所以,我认为在调用 EndReceive 前,先要判断 Socket 是否可用。(这个结论尚未测试)

同时,我测试将Socket.Shutdown(

SocketShutdown.Send ),改为Socket.Shutdown(SocketShutdown.Receive ),并不能引发函数走到 else 部分,所以,我认为Socket 的Shutdown(SocketShutdown.Send )和Close()会引发客户端与服务端的一次数据传输。