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

推荐订阅源

OSCHINA 社区最新新闻
OSCHINA 社区最新新闻
博客园 - Franky
T
Tailwind CSS Blog
Microsoft Azure Blog
Microsoft Azure Blog
The Cloudflare Blog
博客园 - 叶小钗
N
Netflix TechBlog - Medium
罗磊的独立博客
量子位
MyScale Blog
MyScale Blog
A
About on SuperTechFans
Blog — PlanetScale
Blog — PlanetScale
V
Visual Studio Blog
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
GbyAI
GbyAI
B
Blog
腾讯CDC
爱范儿
爱范儿
Recent Announcements
Recent Announcements
有赞技术团队
有赞技术团队
F
Fortinet All Blogs
雷峰网
雷峰网
G
Google Developers Blog
Google DeepMind News
Google DeepMind News

博客园 - YD

如何查找某一函数的定义 Ruby 线程--生产者、消费者 Ruby的函数指针 Rails2.0学习--真困难 加班赶工,得不偿失——历史给你上六课 7. 创建Subversion服务之补充 Task Manager 1.1 开源软件:(Task Manager)任务管理-找出自己最需要完成的任务 小说阅读器 2.0 6. 创建 Subversion 服务 小说阅读器,有兴趣的同志可以试一下 不规则窗体的制作 播放 wave 文件 CRC 校验 C# 实现法 5. 多人协作 C# 中信号量的使用 4. 不要把不必要的文件版本化 3. 从 Repository 中恢复 2. 创建你的 Repository
简单 Socket 通信
YD · 2007-05-06 · via 博客园 - YD

MSDN 上也有个关于 Socket 通信的简单例子。我这是从那上面搬过来的。不过改来改去就变得跟原来的差得不少了。我觉得比 MSDN 上的例子会更好一点。因为可以自己定义要传送的数据类型,只要要传送的数据是可以序列化的。

我把程序分成两大块:PostOffice,Package。PostOffice 实现收发功能,相当于邮局。Package 包含了这个包的类型和包里面要传送的数据。

Package 类的定义:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;

namespace TalkDemo.Core
{
    [Serializable]
    
public class Package
    
{
        
private PackageType packageType;

        
public PackageType PackageType
        
{
            
get return packageType; }
        }


        
private IPEndPoint sourceEP;

        
public IPEndPoint SourceEP
        
{
            
get return sourceEP; }
        }


        
private IPEndPoint destEP;

        
public IPEndPoint DestEP
        
{
            
get return destEP; }
        }


        
private object[] data;

        
public object[] Data
        
{
            
get return data; }
        }


        
public Package(PackageType packageType, IPEndPoint sourceEP, IPEndPoint destEP,
            
params object[] data)
        
{
            
this.packageType = packageType;
            
this.sourceEP = sourceEP;
            
this.destEP = destEP;
            
this.data = data;
        }


        
public static void Serialize(Stream stream, Package package)
        
{
            
if (package == nullreturn;
            
if (stream == nullreturn;

            BinaryFormatter binFormatter 
= new BinaryFormatter();
            binFormatter.Serialize(stream, package);
        }


        
public static Package Deserialize(Stream stream)
        
{
            
if (stream == nullreturn null;

            BinaryFormatter binFormatter 
= new BinaryFormatter();
            Package package;
            
try
            
{
                package 
= binFormatter.Deserialize(stream) as Package;
            }

            
catch
            
{
                
return null;
            }


            
return package;
        }

    }

}

PackageType 枚举的定义:

namespace TalkDemo.Core
{
    
public enum PackageType
    
{
        Data,
        ExitSignal,
    }

}

using System;
using System.Collections.Generic;
using System.Text;

namespace TalkDemo.Core
{
    
public class PackageReceivedEventArgs
        : EventArgs
    
{
        
private Package package;

        
public Package Package
        
{
            
get return package; }
        }


        
public PackageReceivedEventArgs(Package package)
        
{
            
this.package = package;
        }

    }

}


namespace TalkDemo.Core
{
    
public delegate void PackageReceivedEventhandler(object sender, PackageReceivedEventArgs e);
}

PostOffice 的定义:

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.IO;
using System.Net;
using System.Threading;

namespace TalkDemo.Core
{
    
public sealed class PostOffice
    
{
        
Fields

        
Properties

        
Methods

        
Enumerations

        
Events

        
private class AcceptCallArgs
        
{
            
private Socket socket;

            
public Socket Socket
            
{
                
get return socket; }
            }


            
private ListenAs role;

            
public ListenAs Role
            
{
                
get return role; }
            }


            
public AcceptCallArgs(Socket socket, ListenAs role)
            
{
                
this.socket = socket;
                
this.role = role;
            }

        }

    }

}

可以看出来,这里发送是同步的,但接收是异步的。这个程序也算是个怪胎了!@#@#¥#,不过全当练习了。

有了这个通信的核心,就可以做个简单的双向通信程序了。

using System;
using System.Collections.Generic;
using System.Text;
using TalkDemo.Core;
using System.Net;

namespace TalkTest.Ui
{
    
class Program
    
{
        
static void Main(string[] args)
        
{
            PostOffice postOffice 
= PostOffice.Instance;
            
try
            
{
                Console.Write(
"Target ip: ");
                
string targetIp = Console.ReadLine();

                IPHostEntry targetEntry 
= Dns.GetHostEntry(targetIp);
                IPEndPoint targetEP 
= new IPEndPoint(targetEntry.AddressList[0], PostOffice.ClientPort);

                postOffice.PackageReceived 
+= new PackageReceivedEventhandler(postOffice_PackageReceived);
                postOffice.BeginListen(PostOffice.ListenAs.Client);

                Console.Write(
"Talk Demo> ");
                
string input = Console.ReadLine();
                
while (!input.ToLower().Equals("exit"))
                
{
                    Package p 
= new Package(PackageType.Data, postOffice.LocalClientEP, targetEP, input);

                    
try
                    
{
                        postOffice.Send(p);
                    }

                    
catch (Exception ex)
                    
{
                        Console.WriteLine(ex.Message);
                    }


                    Console.Write(
"Talk Demo> ");
                    input 
= Console.ReadLine();
                }

            }

            
catch (Exception ex)
            
{
                Console.WriteLine(ex.Message);
            }

            
finally
            
{
                postOffice.EndListen(PostOffice.ListenAs.Client);
            }


            Console.WriteLine(
"Press any key to continue");
            Console.ReadKey(
true);
        }


        
static void postOffice_PackageReceived(object sender, PackageReceivedEventArgs e)
        
{
            
if (e.Package.PackageType == PackageType.Data)
            
{
                Console.WriteLine(
"\r\nFrom [" + e.Package.SourceEP.Address.ToString() + "]> " + e.Package.Data[0].ToString());
                Console.Write(
"Talk Demo> ");
            }

        }

    }

}