`
luozhong915127
  • 浏览: 188822 次
  • 性别: Icon_minigender_1
  • 来自: 湖南
文章分类
社区版块
存档分类
最新评论

C#中UDP通信和TCP通信的差异

阅读更多

C#UDPTCP通信的详解

可以看到这个处理的基本步骤如下:    

  执行Receive函数,接收远程socket发送的信息;    

  把信息从字节转换到string;    

  处理该信息,然后进入下一个循环,继续等待socket发送新的信息。    

值得注意的有几个:    

  1Receive函数。这个函数和ListenerAccept函数类似。在这个地方等待执行,如果没有新的消息,这个函数就不会执行下一句,一直等待。    

  2:接收的是字节流,需要转化成字符串    

  3:判断远程关闭联接的方式    

  4:如果对方的消息非常大,还得循环接收这个data。    

4:如何管理这些联接(thread)    

通过上边的程序,基本上可以建立一个侦听,并且处理联接会话。但是如何管理这些thread呢?不然大量产生thread可是一个灾难。    

管理的方法比较简单,在Listener里面我定义了一个静态的哈希表(static public Hashtable Connections=new Hashtable();),存储Connection实例和它对应的Thread实例。而connection中也加入了一个最后联接时间的定义(private DateTime _lastConnectTime;)。在新链接建立的时候(ListenerAccept()之后)就把Connection实例和Thread实例存到哈希表中;在ConnectionReceive的时候修改最后联接时间。这样我们就可以知道该Connection在哪里,并且会话是否活跃。    

然后在Winform程序里头可以管理这些会话了,设置设置超时。    

  

在网络环境下,我们最感兴趣的两个命名空间是System.Net和 System.Net.SocketsSystem.Net命名空间通常与较高程的操作有关,例如downloadupload,试用HTTP和其他协议进行Web请求等等,而System.Net.Sockets命名空间所包含的类通常与较低程的操作有关。如果要直接使用Sockets或者 TCP/IP之类的协议,这个命名空间的类是非常有用的。    

  在.Net中,System.Net.Sockets 命名空间为需要严密控制网络访问的开发人员提供了 Windows Sockets (Winsock) 接口的托管实现。System.Net 命名空间中的所有其他网络访问类都建立在该套接字Socket实现之上,如TCPClientTCPListener 和 UDPClient 类封装有关创建到 Internet 的 TCP 和 UDP 连接的详细信息;NetworkStream类则提供用于网络访问的基础数据流等,常见的许多Internet服务都可以见到Socket的踪影,如 TelnetHttpEmailEcho等,这些服务尽管通讯协议Protocol的定义不同,但是其基础的传输都是采用的Socket。    

  其实,Socket可以象流Stream一样被视为一个数据通道,这个通道架设在应用程序端(客户端)和远程服务器端之间,而后,数据的读取(接收)和写入(发送)均针对这个通道来进行。    

  可见,在应用程序端或者服务器端创建了Socket对象之后,就可以使用Send/SentTo方法将数据发送到连接的Socket,或者使用Receive/ReceiveFrom方法接收来自连接Socket的数据。    

  针对Socket编程,.NET 框架的 Socket 类是 Winsock32 API 提供的套接字服务的托管代码版本。其中为实现网络编程提供了大量的方法,大多数情况下,Socket 类方法只是将数据封送到它们的本机 Win32 副本中并处理任何必要的安全检查。如果你熟悉Winsock API函数,那么用Socket类编写网络程序会非常容易,当然,如果你不曾接触过,也不会太困难,跟随下面的解说,你会发觉使用Socket类开发 windows 网络应用程序原来有规可寻,它们在大多数情况下遵循大致相同的步骤。    

  在使用之前,你需要首先创建Socket对象的实例,这可以通过Socket类的构造方法来实现:    

public Socket(AddressFamily addressFamily,SocketType socketType,ProtocolType protocolType);    

  其中,addressFamily 参数指定 Socket 使用的寻址方案,socketType 参数指定 Socket 的类型,protocolType 参数指定 Socket 使用的协议。    

  下面的示例语句创建一个 Socket,它可用于在基于 TCP/IP 的网络(如 Internet)上通讯。    

Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);    

  若要使用 UDP 而不是 TCP,需要更改协议类型,如下面的示例所示:    

Socket temp = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);    

  一旦创建 Socket,在客户端,你将可以通过Connect方法连接到指定的服务器,并通过Send/SendTo方法向远程服务器发送数据,而后可以通过 Receive/ReceiveFrom从服务端接收数据;而在服务器端,你需要使用Bind方法绑定所指定的接口使Socket与一个本地终结点相联,并通过Listen方法侦听该接口上的请求,当侦听到用户端的连接时,调用Accept完成连接的操作,创建新的Socket以处理传入的连接请求。使用完 Socket 后,记住使用 Shutdown 方法禁用 Socket,并使用 Close 方法关闭 Socket。    

  可以看出,以上许多方法包含EndPoint类型的参数,在Internet中,TCP/IP 使用一个网络地址和一个服务端口号来唯一标识设备。网络地址标识网络上的特定设备;端口号标识要连接到的该设备上的特定服务。网络地址和服务端口的组合称为终结点,在 .NET 框架中正是由 EndPoint 类表示这个终结点,它提供表示网络资源或服务的抽象,用以标志网络地址等信息。.Net同时也为每个受支持的地址族定义了 EndPoint 的子代;对于 IP 地址族,该类为 IPEndPointIPEndPoint 类包含应用程序连接到主机上的服务所需的主机和端口信息,通过组合服务的主机IP地址和端口号,IPEndPoint 类形成到服务的连接点。    

  用到IPEndPoint类的时候就不可避免地涉及到计算机IP地址,System.Net命名空间中有两种类可以得到IP地址实例:    

  IPAddress类:IPAddress 类包含计算机在 IP 网络上的地址。其Parse方法可将 IP 地址字符串转换为 IPAddress 实例。下面的语句创建一个 IPAddress 实例:    

IPAddress myIP = IPAddress.Parse("192.168.0.1");    

  Dns 类:向使用 TCP/IP Internet 服务的应用程序提供域名服务。其Resolve 方法查询 DNS 服务器以将用户友好的域名(如"host.mydomain.com")映射到数字形式的 Internet 地址(如 192.168.0.1)。Resolve方法 返回一个 IPHostEnty 实例,该实例包含所请求名称的地址和别名的列表。大多数情况下,可以使用 AddressList 数组中返回的第一个地址。下面的代码获取一个 IPAddress 实例,该实例包含服务器 host.mydomain.com 的 IP 地址。    

IPHostEntry ipHostInfo = Dns.Resolve("host.mydomain.com ");    

IPAddress ipAddress = ipHostInfo.AddressList[0];    

  你也可以使用GetHostName方法得到IPHostEntry实例:    

IPHosntEntry hostInfo=Dns.GetHostByName("host.mydomain.com ")    

  在使用以上方法时,你将可能需要处理以下几种异常:    

  SocketException异常:访问Socket时操作系统发生错误引发    

  ArgumentNullException异常:参数为空引用引发    

  ObjectDisposedException异常:Socket已经关闭引发    

  在掌握上面得知识后,下面的代码将该服务器主机( host.mydomain.com的 IP 地址与端口号组合,以便为连接创建远程终结点:    

IPEndPoint ipe = new IPEndPoint(ipAddress,11000);    

  确定了远程设备的地址并选择了用于连接的端口后,应用程序可以尝试建立与远程设备的连接。下面的示例使用现有的 IPEndPoint 实例与远程设备连接,并捕获可能引发的异常:    

try    

{    

temp.Connect(ipe);//尝试连接    

}    

//处理参数为空引用异常    

catch(ArgumentNullException ae)    

{    

Console.WriteLine("ArgumentNullException : {0}", ae.ToString());    

}    

//处理操作系统异常    

catch(SocketException se)    

{    

Console.WriteLine("SocketException : {0}", se.ToString());    

}    

    

 
namespace UDPServer    
  
{    
  
    class Program    
  
    {    
  
        static void Main(string[] args)    
  
        {    
  
            int recv;    
  
            byte[] data = new byte[1024];    
  
            //构建TCP 服务器    
  
            //得到本机IP,设置TCP端口号             
  
            IPEndPoint ipep = new IPEndPoint(IPAddress.Any , 8001);    
  
            Socket newsock = new Socket(AddressFamily.InterNetwork, SocketType.Dgram , ProtocolType.Udp);    
  
            //绑定网络地址    
  
            newsock.Bind(ipep);    
  
            Console.WriteLine("This is a Server, host name is {0}",Dns.GetHostName());    
  
            //等待客户机连接    
  
            Console.WriteLine("Waiting for a client...");    
  
            //得到客户机IP    
  
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);    
  
            EndPoint Remote = (EndPoint)(sender);    
  
            recv = newsock.ReceiveFrom(data, ref Remote);    
  
            Console .WriteLine ("Message received from {0}: ", Remote.ToString ());    
  
            Console .WriteLine (Encoding .ASCII .GetString (data ,0,recv ));    
  
            //客户机连接成功后,发送欢迎信息    
  
            string welcome = "Welcome ! ";    
  
            //字符串与字节数组相互转换    
  
            data  = Encoding .ASCII .GetBytes (welcome );    
  
            //发送信息    
  
            newsock .SendTo (data ,data.Length ,SocketFlags .None ,Remote );    
  
            while (true )    
  
            {    
  
                data =new byte [1024];    
  
                //发送接受信息    
  
                recv =newsock.ReceiveFrom(data ,ref Remote);    
  
                Console .WriteLine (Encoding .ASCII .GetString (data ,0,recv));    
  
                newsock .SendTo (data ,recv ,SocketFlags .None ,Remote );    
  
            }    
  
        }    
  
        }    
  
    }    
  
C# code   
using System;   
using System.Collections.Generic;   
using System.Linq;   
using System.Text;   
using System.Net;   
using System.Net.Sockets;   
namespace UDPClient   
{   
    class Program   
    {   
        static void Main(string[] args)   
        {   
            byte[] data = new byte[1024];   
            string input ,stringData;   
            //构建TCP 服务器   
            Console.WriteLine("This is a Client, host name is {0}", Dns.GetHostName());   
            //设置服务IP,设置TCP端口号   
            IPEndPoint ipep = new IPEndPoint(IPAddress .Parse ("127.0.0.1") , 8001);   
            //定义网络类型,数据连接类型和网络协议UDP   
            Socket server = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);   
            string welcome = "Hello! ";   
            data = Encoding.ASCII.GetBytes(welcome);   
            server.SendTo(data, data.Length, SocketFlags.None, ipep);   
            IPEndPoint sender = new IPEndPoint(IPAddress.Any, 0);   
            EndPoint Remote = (EndPoint)sender;   
            data = new byte[1024];   
            int recv = server.ReceiveFrom(data, ref Remote);   
            Console.WriteLine("Message received from {0}: ", Remote.ToString());   
            Console.WriteLine(Encoding .ASCII .GetString (data,0,recv));   
            while (true)   
            {   
                input = Console .ReadLine ();   
                if (input =="exit")   
                    break ;   
                server .SendTo (Encoding .ASCII .GetBytes (input ),Remote );   
                data = new byte [1024];   
                recv = server.ReceiveFrom(data, ref Remote);   
                stringData = Encoding.ASCII.GetString(data, 0, recv);   
                Console.WriteLine(stringData);   
            }   
            Console .WriteLine ("Stopping Client.");   
            server .Close ();               
        }   
        }   
    }    
  
C# code   
TCPClient   
/*TCPClient 类提供了一种使用 TCP 协议连接到某个端点的简化方法。它还通  *过 NetworkStream 对象展现在连接过程中读取或写入的数据。请参见下面从 *QuickStart 文档中摘录的日期/时间客户机示例。
*/   
//使用 C# 编写   
using System;   
using System.Net;   
using System.Net.Sockets;   
using System.IO;   
using System.Text;   
class Client   
{   
public static void Main(String[] args)   
{   
TCPClient tcpc = new TCPClient();   
Byte[] read = new Byte[32];   
if (args.Length != 1)   
{   
Console.WriteLine(“请在命令行中指定服务器名称”);   
return;   
}   
String server = args[0];   
// 验证服务器是否存在   
if (DNS.GetHostByName(server) == null)   
{   
Console.WriteLine(“找不到服务器:” + 服务器);   
return;   
}   
// 尝试连接到服务器   
if (tcpc.Connect(server, 13) == -1)   
{   
Console.WriteLine(“无法连接到服务器:” + 服务器);   
return;   
}   
// 获取流   
Stream s = tcpc.GetStream();   
// 读取流并将它转换为 ASCII 码形式   
int bytes = s.Read(read, 0, read.Length);   
String Time = Encoding.ASCII.GetString(read);   
// 显示数据   
Console.WriteLine(“已接收到的” + 字节 + “字节”);   
Console.WriteLine(“当前日期和时间是:” + 时间);   
tcpc.Close();   
}   
}   
TCPListener   
/*TCPListener 类便于在来自某个客户机的 TCP 连接的特定套接字上进行侦听的*工作。请参见下面包括在 QuickStart 文档中的日期/时间服务器示例。 
*/  
//使用 C# 编写   
using System;   
using System.Net;   
using System.Net.Sockets;   
using System.Text;   
class Server   
{   
public static void Main()   
{   
DateTime now;   
String strDateLine;   
Encoding ASCII = Encoding.ASCII;   
// 在端口 13 进行侦听   
TCPListener tcpl = new TCPListener(13);   
tcpl.Start();   
Console.WriteLine(“正在等待客户进行连接”);   
Console.WriteLine(“请按 Ctrl+c 退出...”);   
while (true)   
{   
// 接收会阻塞,直到有人连接上   
Socket s = tcpl.Accept();   
// 获取当前的日期和时间并将它连接成一个字符串   
now = DateTime.Now;   
strDateLine = now.ToShortDateString() + " " +   
now.ToLongTimeString();   
// 将该字符串转换成一个字节数组并发送它   
Byte[] byteDateLine =   
ASCII.GetBytes(strDateLine.ToCharArray());   
s.Send(byteDateLine, byteDateLine.Length, 0);   
Console.WriteLine(“发送” + strDateLine);   
}   
}   
}   
 
#region "Download: File transfer FROM ftp server"    
        /// <summary>    
        /// Copy a file from FTP server to local    
        /// </summary>    
        /// <param name="sourceFilename">Target filename, if required </param>    
        /// <param name="localFilename">Full path of the local file </param>    
        /// <returns> </returns>    
        /// <remarks>Target can be blank (use same filename), or just a filename    
        /// (assumes current directory) or a full path and filename </remarks>    
        public bool Download(string sourceFilename, string localFilename, bool PermitOverwrite)    
        {    
            //2. determine target file    
            FileInfo fi = new FileInfo(localFilename);    
            return this.Download(sourceFilename, fi, PermitOverwrite);    
        }    
        //Version taking an FtpFileInfo    
        public bool Download(FtpFileInfo file, string localFilename, bool permitOverwrite)    
        {    
            return this.Download(file.FullName, localFilename, permitOverwrite);    
        }    
        //Another version taking FtpFileInfo and FileInfo    
        public bool Download(FtpFileInfo file, FileInfo localFI, bool permitOverwrite)    
        {    
            return this.Download(file.FullName, localFI, permitOverwrite);    
        }    
        //Version taking string/FileInfo    
        public bool Download(string sourceFilename, FileInfo targetFI, bool permitOverwrite)    
        {    
            //1. check target    
            if (targetFI.Exists && !(permitOverwrite))    
            {    
                throw (new ApplicationException("Target file already exists"));    
            }    
            //2. check source    
            string target;    
            if (sourceFilename.Trim() == "")    
            {    
                throw (new ApplicationException("File not specified"));    
            }    
            else if (sourceFilename.Contains("/"))    
            {    
                //treat as a full path    
                target = AdjustDir(sourceFilename);    
            }    
            else    
            {    
                //treat as filename only, use current directory    
                target = CurrentDirectory + sourceFilename;    
            }    
            string URI = Hostname + target;    
            //3. perform copy    
            System.Net.FtpWebRequest ftp = GetRequest(URI);    
            //Set request to download a file in binary mode    
            ftp.Method = System.Net.WebRequestMethods.Ftp.DownloadFile;    
            ftp.UseBinary = true;    
            //open request and get response stream    
            using (FtpWebResponse response = (FtpWebResponse)ftp.GetResponse())    
            {    
                using (Stream responseStream = response.GetResponseStream())    
                {    
                    //loop to read & write to file    
                    using (FileStream fs = targetFI.OpenWrite())    
                    {    
                        try    
                        {    
                            byte[] buffer = new byte[2048];    
                            int read = 0;    
                            do    
                            {    
                                read = responseStream.Read(buffer, 0, buffer.Length);    
                                fs.Write(buffer, 0, read);    
                            } while (!(read == 0));    
                            responseStream.Close();    
                            fs.Flush();    
                            fs.Close();    
                        }    
                        catch (Exception)    
                        {    
                            //catch error and delete file only partially downloaded    
                            fs.Close();    
                            //delete target file as it's incomplete    
                            targetFI.Delete();    
                            throw;    
                        }    
                    }    
                    responseStream.Close();    
                }    
                response.Close();    
            }    
            return true;    
        }   
        #endregion    
  
简单的UDP收发.    
发送    
C# code   
                    try  
                    {   
                        Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);  //向此网段发广播包   
                          int UDPListenerPort = 8082;   
                        IPAddress broadcast = IPAddress.Parse("192.168.0.255"); //此处根据IP及子网掩码改为相应的广播IP   
                        string ts = "This is UPD string for sending";   
                        byte[] sendbuf = Encoding.ASCII.GetBytes(ts);   
                        IPEndPoint ep = new IPEndPoint(broadcast, UDPListenerPort);   
                        s.SendTo(sendbuf, ep);   
                    }   
                    catch (Exception e)   
                    {}   
接收    
C# code   
           UdpClient listener;   
            int UDPListenerPort = 8082;   
            IPEndPoint groupEP = new IPEndPoint(IPAddress.Any, UDPListenerPort);   
            try  
            {   
                while (true)   
                {   
                    byte[] bytes = listener.Receive(ref groupEP);   
                    string RecIP = groupEP.ToString().Substring(0, groupEP.ToString().IndexOf(":"));  //收到发送UPD端的IP   
                    string RecStr = Encoding.ASCII.GetString(bytes, 0, bytes.Length);   //收到的UPD字符串   
                }   
            }   
            catch  
            {}    
  
C# code    
TCPClient    
TCPClient 类提供了一种使用 TCP 协议连接到某个端点的简化方法。它还通过 NetworkStream 对象展现在连接过程中读取或写入的数据。请参见下面从 QuickStart 文档中摘录的日期/时间客户机示例。    
使用 C# 编写    
using System;    
using System.Net;    
using System.Net.Sockets;    
using System.IO;    
using System.Text;    
class Client    
{    
public static void Main(String[] args)    
{    
TCPClient tcpc = new T…    
  
来一个Remoting的:    
C# code   
using System;    
namespace Remotable    
{    
    public class RemotableType : MarshalByRefObject    
    {    
        private string _internalString = "This is the RemotableType.";    
        public string StringMethod()    
        {    
            return _internalString;    
        }    
    }    
}    
using System;    
using System.Runtime.Remoting;    
namespace RemotingFirst    
{    
    public class Listener    
    {    
        public static void Main()    
        {    
            RemotingConfiguration.Configure("Listener.exe.config");    
            Console.WriteLine("Listening for requests. Press Enter to exit");    
            Console.ReadLine();    
        }    
    }    
}    
using System;    
using System.Runtime.Remoting;    
namespace Client    
{    
    public class Client    
    {    
        public static void Main()    
        {    
            RemotingConfiguration.Configure("Client.exe.config");    
            Remotable.RemotableType remoteObject = new Remotable.RemotableType();    
            Console.WriteLine(remoteObject.StringMethod());    
        }    
    }    
}    
Listener.exe.config    
<?xml version="1.0" encoding="utf-8" ?>    
<configuration>    
    <system.runtime.remoting>    
      <application>    
         <service>    
            <wellknown     
               mode="Singleton"     
               type="Remotable.RemotableType, RemotableType"     
               objectUri="RemotableType.rem"    
            />    
         </service>    
         <channels>    
            <channel ref="http" port="8989"/>    
         </channels>    
      </application>    
    </system.runtime.remoting>    
</configuration>    
  
实只要用到Socket联接,基本上就得使用Thread,是交叉使用的。    
C#封装的Socket用法基本上不算很复杂,只是不知道托管之后的Socket有没有其他性能或者安全上的问题。    
在C#里面能找到的最底层的操作也就是socket了,概念不做解释。    
程序模型如下:    
WinForm程序 : 启动端口侦听;监视Socket联接情况;定期关闭不活动的联接;    
Listener:处理Socket的Accept函数,侦听新链接,建立新Thread来处理这些联接(Connection)。    
Connection:处理具体的每一个联接的会话。    
1:WinForm如何启动一个新的线程来启动Listener:    
      //start the server    
        private void btn_startServer_Click(object sender, EventArgs e)    
        {    
            //this.btn_startServer.Enabled = false;    
            Thread _createServer = new Thread(new ThreadStart(WaitForConnect));    
            _createServer.Start();    
        }    
        //wait all connections    
        private void WaitForConnect()    
        {    
            SocketListener listener = new SocketListener(Convert.ToInt32(this.txt_port.Text));    
            listener.StartListening();    
        }    
/*因为侦听联接是一个循环等待的函数,所以不可能在WinForm的线程里面直接**执行,不然Winform也就是无法继续任何操作了,所以才指定一个新的线程来**执行这个函数,启动侦听循环。    
*这一个新的线程是比较简单的,基本上没有启动的参数,直接指定处理函数就可**以了。    
*2:Listener如何启动循环侦听,并且启动新的带有参数的线程来处理Socket联*接会话。    
*先看如何建立侦听:(StartListening函数) 
*/   
IPEndPoint localEndPoint = new IPEndPoint(_ipAddress, _port);    
        // Create a TCP/IP socket.    
        Socket listener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);    
            // Bind the socket to the local endpoint and  listen for incoming connections.    
            try    
            {    
                listener.Bind(localEndPoint);    
                listener.Listen(20);//20 trucks    
                // Start listening for connections.    
                while (true)    
                {    
                  // here will be suspended while waiting for a new connection.    
                    Socket connection = listener.Accept();    
                    Logger.Log("Connect", connection.RemoteEndPoint.ToString());//log it, new connection    
                ……    
          }    
        }……    
//基本步骤比较简单:    
建立本机的IPEndPoint对象,表示以本机为服务器,在指定端口侦听;    
然后绑定到一个侦听Socket上;    
进入while循环,等待新的联接;    
如果有新的联接,那么建立新的socket来对应这个联接的会话。    
  值得注意的就是这一句联接代码:listener.Accept()。执行这一句的时候,程序就在这个地方等待,直到有新的联检请求的时候程序才会执行下一句。这是同步执行,当然也可以异步执行。    
  新的联接Socket建立了(Accept之后),对于这些新的socket该怎么办呢?他们依然是一个循环等待,所以依然需要建立新的Thread给这些Socket去处理会话(接收/发送消息),而这个Thread就要接收参数了。    
  Thread本身是不能接收参数的,为了让它可以接收参数,可以采用定义新类,添加参数作为属性的方法来解决。    
  因为每一个Socket是一个Connection周期,所以我定义了这么一个类public class Connection。这个类至少有这样一个构造函数public Connection(Socket socket); 之所以这么做,就是为了把Socket参数传给这个Connection对象,然后好让Listener启动这个Thread的时候,Thread可以知道他正在处理哪一个Socket。    
    具体处理的方法:(在Listener的StartListening函数,ocket connection = listener.Accept();之后)    
    Connection gpsCn = new Connection(connection);    
                    //each socket will be wait for data. keep the connection.    
                    Thread thread = new Thread(new ThreadStart(gpsCn.WaitForSendData));    
                    thread.Name = connection.RemoteEndPoint.ToString();    
                    thread.Start();    
如此一来,这个新的socket在Accept之后就在新的Thread中运行了。    
  3:Connection的会话处理    
  建立了新的Connection(也就是socket),远程就可以和这个socket进行会话了,无非就是send和receive。    
  现在先看看怎么写的这个线程运行的Connection. WaitForSendData函数    
    while (true)    
            {    
                bytes = new byte[1024];    
                string data = "";    
                //systm will be waiting the msg of receive envet. like Accept();    
                //here will be suspended while waiting for socket income msg.    
                int bytesRec = this._connection.Receive(bytes);    
                _lastConnectTime = DateTime.Now;    
                if (bytesRec == 0)//close envent    
                {    
                    Logger.Log("Close Connection", _connection.RemoteEndPoint.ToString());    
                    break;    
                }    
                data += Encoding.ASCII.GetString(bytes, 0, bytesRec);    
                //…….handle your data.    
            }    

  需要知道的是:Socket 类支持两种基本模式:同步和异步。其区别在于:在同步模式中,对执行网络操作的函数(如 Send 和 Receive)的调用一直等到操作完成后才将控制返回给调用程序。在异步模式中,这些调用立即返回。    
综合运用以上阐述的使用Visual C#进行Socket网络程序开发的知识,下面的程序是一个简单的Socket通讯实例,client向server发送一段测试字符串,server接收并显示出来,给予client成功相应。    
//client端    
using System;    
using System.Text;    
using System.IO;    
using System.Net;    
using System.Net.Sockets;    
namespace socketsample    
{    
 class Class1    
 {    
  static void Main()    
  {    
   try    
   {    
    int port = 2000;    
    string host = "127.0.0.1";    
    IPAddress ip = IPAddress.Parse(host);    
    IPEndPoint ipe = new IPEndPoint(ip, port);    
    Socket c = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);    
    c.Connect(ipe);    
    string sendStr = "hello!This is a socket test";    
    byte[] bs = Encoding.ASCII.GetBytes(sendStr);    
    c.Send(bs, bs.Length, 0);    
    string recvStr = "";    
    byte[] recvBytes = new byte[1024];    
    int bytes;    
    bytes = c.Receive(recvBytes, recvBytes.Length, 0);    
    recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);    
    Console.WriteLine(recvStr);    
    c.Close();    
   }    
   catch (ArgumentNullException e)    
   {    
    Console.WriteLine("ArgumentNullException: {0}", e);    
   }    
   catch (SocketException e)    
   {    
    Console.WriteLine("SocketException: {0}", e);    
   }    
   Console.ReadLine();    
  }    
 }    
}    
//server端    
using System;    
using System.Text;    
using System.IO;    
using System.Net;    
using System.Net.Sockets;    
namespace Project1    
{    
 class Class2    
 {    
  static void Main()    
  {    
   try    
   {    
    int port = 2000;    
    string host = "127.0.0.1";    
    IPAddress ip = IPAddress.Parse(host);    
    IPEndPoint ipe = new IPEndPoint(ip, port);    
    Socket s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);    
    s.Bind(ipe);    
    s.Listen(0);    
    Socket temp = s.Accept();    
    string recvStr = "";    
    byte[] recvBytes = new byte[1024];    
    int bytes;    
    bytes = temp.Receive(recvBytes, recvBytes.Length, 0);    
    recvStr += Encoding.ASCII.GetString(recvBytes, 0, bytes);    
    Console.WriteLine(recvStr);    
    string sendStr = "Ok!Sucess!";    
    byte[] bs = Encoding.ASCII.GetBytes(sendStr);    
    temp.Send(bs, bs.Length, 0);    
    temp.Shutdown(SocketShutdown.Both);    
    temp.Close();    
    s.Shutdown(SocketShutdown.Both);    
    s.Close();    
   }    
   catch (ArgumentNullException e)    
   {    
    Console.WriteLine("ArgumentNullException: {0}", e);    
   }    
   catch (SocketException e)    
   {    
    Console.WriteLine("SocketException: {0}", e);    
   }    
   Console.ReadLine();    
  }    
 }    
}    
     
  
C#UDP的多路广播组的发送和接收    
下列范例使用 UdpClient,在通讯端口11000传送UDP 资料包至多点传送位址群组 224.268.100.2。它传送命令列上指定的信息字串。     
C# code    
using System;     
using System.Net;     
using System.Net.Sockets;     
using System.Text;     
public class UDPMulticastSender {     
private static IPAddress GroupAddress =     
IPAddress.Parse("224.168.100.2");     
private static int GroupPort = 11000;     
private static void Send( String message) {     
UdpClient sender = new UdpClient();     
IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort);     
try {     
Console.WriteLine("Sending datagram : {0}", message);     
byte[] bytes = Encoding.ASCII.GetBytes(message);     
sender.Send(bytes, bytes.Length, groupEP);     
sender.Close();     
} catch (Exception e) {     
Console.WriteLine(e.ToString());     
}     
}     
public static int Main(String[] args) {     
Send(args[0]);     
return 0;     
}     
}      
  
下列范例使用 UdpClient,在通讯端口  11000  监听广播到多点传送位址群组 224.168.100.2 的 UDP  资料包。它接收信息字串,并將信息写入主控台 (Console)。      
  
C# code    
  
using System;      
  
using System.Net;      
  
using System.Net.Sockets;      
  
using System.Text;      
  
public class UDPMulticastListener {      
  
private static readonly IPAddress GroupAddress =      
  
IPAddress.Parse("224.168.100.2");      
  
private const int GroupPort = 11000;      
  
private static void StartListener() {      
  
bool done = false;      
  
UdpClient listener = new UdpClient();      
  
IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort);      
  
try {      
  
listener.JoinMulticastGroup(GroupAddress);      
  
listener.Connect(groupEP);      
  
while (!done) {      
  
Console.WriteLine("Waiting for broadcast");      
  
byte[] bytes = listener.Receive( ref groupEP);      
  
Console.WriteLine("Received broadcast from {0} :\n {1}\n",      
  
groupEP.ToString(),      
  
Encoding.ASCII.GetString(bytes,0,bytes.Length));      
  
}      
  
listener.Close();      
  
} catch (Exception e) {      
  
Console.WriteLine(e.ToString());      
  
}      
  
}      
  
public static int Main(String[] args) {      
  
StartListener();      
  
return 0;      
  
}      
  
}    
  
using System;      
  
using System.Net;      
  
using System.Net.Sockets;      
  
using System.Text;      
  
public class UDPMulticastSender {      
  
private static IPAddress GroupAddress =      
  
IPAddress.Parse("224.168.100.2");      
  
private static int GroupPort = 11000;      
  
private static void Send( String message) {      
  
UdpClient sender = new UdpClient();      
  
IPEndPoint groupEP = new IPEndPoint(GroupAddress,GroupPort);      
  
try {      
  
Console.WriteLine("Sending datagram : {0}", message);      
  
byte[] bytes = Encoding.ASCII.GetBytes(message);      
  
sender.Send(bytes, bytes.Length, groupEP);      
  
sender.Close();      
  
} catch (Exception e) {      
  
Console.WriteLine(e.ToString());      
  
}      
  
}      
  
public static int Main(String[] args) {      
  
Send(args[0]);      
  
return 0;      
  
}      
  
}    
  
C# code    
  
try    
  
                {    
  
                    UdpClient udp=new UdpClient(new IPEndPoint(ipAddress,startPort+i));    
  
                    udp.Close();                        
  
                    unUsedPort=startPort+i;    
  
                    break;    
  
                }    
  
                catch    
  
                {    
  
                }    
  
using System;    
  
using System.Collections.Generic;    
  
using System.ComponentModel;    
  
using System.Data;    
  
using System.Drawing;    
  
using System.Text;    
  
using System.Windows.Forms;    
  
using System.Collections;    
  
using System.Collections.Specialized;    
  
using System.Threading;    
  
using System.Net.Sockets;    
  
using System.Net;    
  
using System.Runtime.Serialization;    
  
using System.Runtime.Serialization.Formatters.Binary;    
  
using System.IO;    
  
namespace 聊天工具服务器    
  
{    
  
    public partial class FormMain : Form    
  
    {    
  
        public FormMain()    
  
        {    
  
            InitializeComponent();    
  
        }   
 
        #region 字段定义    
  
        /// <summary>    
  
        /// 服务器程序使用的端口,默认为8888    
  
        /// </summary>    
  
        private int _port = 8888;    
  
        /// <summary>    
  
        /// 接收数据缓冲区大小2K    
  
        /// </summary>    
  
        private const int _maxPacket =2 * 1024;    
  
        /// <summary>    
  
        /// 服务器端的监听器    
  
        /// </summary>    
  
        private TcpListener _tcpl = null;    
  
        Thread _receiveThread;    
  
        /// <summary>    
  
        /// 保存所有客户端会话的哈希表    
  
        /// </summary>    
  
        private Hashtable _transmit_tb = new Hashtable();    
  
        /// <summary>    
  
        /// 当前文件路径    
  
        /// </summary>    
  
        string MyPath = null;    
  
        /// <summary>    
  
        /// 用户基本信息表,包括UserName,UserPwd,UserNich,UserImg,ZX,UserIp    
  
        /// </summary>    
  
        DataTable TabUser = new DataTable();    
  
        /// <summary>    
  
        /// 用户消息表,保存用户不在线时的消息    
  
        /// </summary>    
  
        DataTable TabUserMessage = new DataTable();   
 
        #endregion    
  
        /// <summary>    
  
        /// 序列化在线列表,向客户端返回序列化后的字节数组    
  
        /// </summary>    
  
        /// <returns>序列化后的字节数组 </returns>    
  
        private byte[] SerializeOnlineList()    
  
        {    
  
            StringCollection onlineList = new StringCollection();    
  
            foreach (object o in _transmit_tb.Keys)    
  
            {    
  
                onlineList.Add(o as string);    
  
            }    
  
            IFormatter format = new BinaryFormatter();    
  
            MemoryStream stream = new MemoryStream();    
  
            format.Serialize(stream, onlineList);    
  
            byte[] ret = stream.ToArray();    
  
            stream.Close();    
  
            return ret;    
  
        }    
  
        /// <summary>    
  
        /// 序列化好友列表,向客户端返回序列化后的datatable    
  
        /// </summary>    
  
        /// <returns>序列化后的字节数组 </returns>    
  
        private bool SerializeFriendList(object obj, Socket clientSkt)    
  
        {    
  
            DataTable TabmyFriend = new DataTable();    
  
            TabmyFriend.TableName = obj as string;    
  
            try {    
  
                TabmyFriend.ReadXml(MyPath + "\\UserFriend\\" + TabmyFriend.TableName + ".xml");    
  
                TabmyFriend.Columns.Add("UserImg", typeof(String));    
  
                TabmyFriend.Columns.Add("UserNich", typeof(String));    
  
                TabmyFriend.Columns.Add("ZX", typeof(Boolean));    
  
                TabmyFriend.Columns.Add("UserIp", typeof(String));    
  
                foreach (DataRow myrow in TabmyFriend.Rows)    
  
                {    
  
                    DataRow[] DataRows = TabUser.Select(" UserName = '" + myrow["UserName"].ToString() + "'");    
  
                    if (DataRows.Length > 0)    
  
                    {    
  
                        myrow["UserImg"] = DataRows[0]["UserImg"].ToString();    
  
                        myrow["UserNich"] = DataRows[0]["UserNich"].ToString();    
  
                      try    
  
                      {    
  
                            myrow["ZX"] = (bool)DataRows[0]["ZX"];    
  
                            myrow["UserIp"] = DataRows[0]["UserIp"].ToString();    
  
                      }       
  
                      catch    
  
                        {    
  
                            myrow["ZX"] = false;    
  
                            myrow["UserIp"] = "";    
  
                        }    
  
                    }    
  
                }    
  
            }    
  
            catch    
  
            {    
  
                TabmyFriend.Columns.Add("UserName", typeof(String));    
  
                TabmyFriend.Columns.Add("UserImg", typeof(String));    
  
                TabmyFriend.Columns.Add("ZX", typeof(Boolean));    
  
                TabmyFriend.Columns.Add("UserIp", typeof(String));    
  
            }    
  
            IFormatter format = new BinaryFormatter();    
  
            MemoryStream stream = new MemoryStream();    
  
            format.Serialize(stream, TabmyFriend);    
  
            stream.Position = 0;    
  
            byte[] ret = new byte[_maxPacket];    
  
            int count = 0;    
  
            count = stream.Read(ret, 0, _maxPacket);    
  
            //先发送响应信号,用户客户机的判断    
  
            clientSkt.Send(Encoding.Unicode.GetBytes("cmd::RequestFriendList"));    
  
            while (count >0)    
  
            {    
  
                clientSkt.Send(ret);    
  
                count =  stream.Read(ret, 0, _maxPacket);    
  
              }    
  
            //发送结束信号    
  
              clientSkt.Send(Encoding.Unicode.GetBytes("Find::RequestFriendListEnd"));      
  
              stream.Close();    
  
            return true ;    
  
        }    
  
        private void FormMain_Load(object sender, EventArgs e)    
  
        {    
  
            MyPath = Application.StartupPath;    
  
            Read_User();    
  
            ReadTabUserMessage();    
  
            _receiveThread = new Thread(new ThreadStart(StartUp));    
  
            _receiveThread.Start();    
  
        }    
  
        /// <summary>    
  
        /// 读取所有用户信息    
  
        /// </summary>    
  
        private void Read_User()    
  
        {    
  
            try    
  
            {    
  
                TabUser.ReadXml(MyPath + "\\User.xml");    
  
            }    
  
            catch    
  
            {    
  
                TabUser.TableName = "User";    
  
                TabUser.Columns.Add("UserName", typeof(String));    
  
                TabUser.Columns.Add("UserPwd", typeof(String));    
  
                TabUser.Columns.Add("UserNich", typeof(String));    
  
                TabUser.Columns.Add("UserImg", typeof(String));    
  
            }    
  
            TabUser.Columns.Add("ZX", typeof(Boolean));    
  
            TabUser.Columns.Add("UserIp", typeof(String));    
  
        }    
  
        /// <summary>    
  
        /// 新用户上/下线后,更新其好友的(好友列表)    
  
        /// </summary>    
  
        /// <param name="UserName"> </param>    
  
        /// <param name="OnLine"> </param>    
  
        /// <param name="IpAddress"> </param>    
  
        private void UpdateFriendList(string UserName, bool OnLine, string IpAddress)    
  
        {    
  
            DataTable TabmyFriend = new DataTable();    
  
            TabmyFriend.TableName = UserName;    
  
            string svrlog = null;    
  
            string []UserInformation = new string[2];//UserName + "$" + IpAddress;    
  
            UserInformation[0] = UserName;    
  
            UserInformation[1] = IpAddress;    
  
            IFormatter format = new BinaryFormatter();    
  
            MemoryStream stream = new MemoryStream();    
  
            format.Serialize(stream, UserInformation);    
  
            byte[] ret = stream.ToArray();    
  
            stream.Close();    
  
            if (OnLine)    
  
            {    
  
                svrlog = "cmd::RequestAddFriendList";    
  
            }    
  
            else    
  
            {    
  
                svrlog = "cmd::RequestRemoveFriendList";    
  
                DataRow[] DataRows = TabUser.Select(" UserName = '" + UserName + "'");    
  
                if (DataRows.Length > 0)    
  
                {    
  
                    DataRows[0]["ZX"] = false;    
  
                    DataRows[0]["UserIp"] = "";    
  
                }    
  
            }    
  
            try    
  
            {    
  
                TabmyFriend.ReadXml(MyPath + "\\UserFriend\\" + TabmyFriend.TableName + ".xml");    
  
                foreach (DataRow myrow in TabmyFriend.Rows)    
  
                {    
  
                    if(_transmit_tb.ContainsKey(myrow["UserName"].ToString()))    
  
                    {    
  
                        Socket _clientSkt = _transmit_tb[myrow["UserName"].ToString()] as Socket;    
  
                      _clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));    
  
                      _clientSkt.Send(ret);    
  
                    }    
  
                }    
  
            }    
  
            catch    
  
            { }    
  
        }    
  
[code=C#][/code /// <summary>    
  
        /// 线程执行体,转发消息    
  
        /// </summary>    
  
        /// <param name="obj">传递给线程执行体的用户名,用以与用户通信 </param>    
  
        private void ThreadFunc(object obj)    
  
        {    
  
            //通过转发表得到当前用户套接字    
  
            Socket clientSkt = _transmit_tb[obj] as Socket;    
  
          //主循环    
  
            while (true)    
  
            {    
  
                try    
  
                {    
  
         //接受第一个数据包。    
  
        //由于程序逻辑结构简单,所以在这里对客户机发送的第一个包内容作逐一判断,    
  
        //这里的实现不够优雅,但不失为此简单模型的一个解决之道。    
  
                    byte[] packetBuff = new byte[_maxPacket];    
  
                    clientSkt.Receive(packetBuff);    
  
                    string _str = Encoding.Unicode.GetString(packetBuff).TrimEnd('\0');    
  
                    //如果是发给不在线好友的信息    
  
                    if (_str.StartsWith("cmd::FriendMessage"))    
  
                    {    
  
                        string UserName = _str.Substring("cmd::FriendMessage".Length, 20).Trim();    
  
                        string MessageS = _str.Substring("cmd::FriendMessage".Length + 20, _str.Length - "cmd::FriendMessage".Length - 20);    
  
                        SaveMessage(obj as string, UserName, MessageS);    
  
                        continue;    
  
                    }    
  
                    //如果是离线请求    
  
                    if (_str.StartsWith("cmd::RequestLogout"))    
  
                    {    
  
                        _transmit_tb.Remove(obj);    
  
                        UpdateFriendList((string)obj, false, "");    
  
                      //  string svrlog = string.Format("[系统消息]用户 {0} 在 {1} 已断开... 当前在线人数: {2}\r\n\r\n", obj, DateTime.Now, _transmit_tb.Count);    
  
                      //  Console.WriteLine(svrlog);    
  
                        //向所有客户机发送系统消息    
  
                        //foreach (DictionaryEntry de in _transmit_tb)    
  
                        //{    
  
                        //    string _clientName = de.Key as string;    
  
                        //    Socket _clientSkt = de.Value as Socket;    
  
                        //    _clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));    
  
                        //}    
  
                        Thread.CurrentThread.Abort();    
  
                    }    
  
                    //如果是请求好友列表    
  
                    if (_str.StartsWith("cmd::RequestFriendList"))    
  
                    {    
  
                        SerializeFriendList(obj, clientSkt);                         
  
                        // 将该用户不在线时的信息发送给用户    
  
                        DataTable TabMessage = ReadMessage(obj as string);    
  
                        if (TabMessage != null)    
  
                        {    
  
              foreach (DataRow myrow in TabMessage.Rows)    
  
            {    
               if (myrow["SendUserName"].ToString() == "System::Message")    
  
        {    
  
                                        clientSkt.Send(Encoding.Unicode.GetBytes(myrow["Message"].ToString()));    
  
                                }    
  
                                else    
  
                                {    
  
                                    clientSkt.Send(Encoding.Unicode.GetBytes("cmd::FriendMessage" + myrow["SendUserName"].ToString().PadRight(20, ' ') + myrow["Message"].ToString()));    
  
                                }    
  
                            }    
  
                        }    
  
                        //这里不需要再继续接受后继数据包了,跳出当前循环体。    
  
                        continue;    
  
                    }    
  
                    ////如果是请求好友列表    
  
                    //if (_str.StartsWith("cmd::RequestOnLineList"))    
  
                    //{    
  
                    //    byte[] onlineBuff = SerializeOnlineList();    
  
                    //    //先发送响应信号,用户客户机的判断    
  
                    //    clientSkt.Send(Encoding.Unicode.GetBytes("cmd::RequestOnLineList"));    
  
                    //    clientSkt.Send(onlineBuff);    
  
                    //    //这里不需要再继续接受后继数据包了,跳出当前循环体。    
  
                    //    continue;    
  
                    //}    
  
                    //查找用户    
  
                    if (_str.StartsWith("Find::FindFriend"))    
  
                    {    
  
                        DataTable TabFind = TabUser.Clone();    
  
                        DataRow [] FindRow =null  ;    
  
                        string UserName = _str.Substring("Find::FindFriend".Length, _str.Length - "Find::FindFriend".Length);    
  
                        if (UserName.Equals("Find::WhoOnLine"))    
  
                        { //看谁在线    
  
                            FindRow = TabUser.Select(" ZX = 1");    
  
                        }    
  
                        else//精确查找    
  
                        {    
  
                            FindRow = TabUser.Select("UserName = '" + UserName + "'");    
  
                        }    
  
                        foreach (DataRow myrow in FindRow)    
  
                        {    
  
                            TabFind.ImportRow(myrow);    
  
                        }    
  
                        clientSkt.Send(Encoding.Unicode.GetBytes("Find::FindFriend"));    
  
                        IFormatter format = new BinaryFormatter();    
  
                        MemoryStream stream = new MemoryStream();    
  
                        format.Serialize(stream, TabFind);    
  
                        stream.Position = 0;    
  
                        byte[] ret = new byte[_maxPacket];    
  
                        int count = 0;    
  
                        count = stream.Read(ret, 0, _maxPacket);    
  
                        while (count >0)    
  
                        {    
  
                            clientSkt.Send(ret);    
  
                          count =  stream.Read(ret, 0, _maxPacket);    
  
                        }    
  
                        clientSkt.Send(Encoding.Unicode.GetBytes("Find::FindFriendEnd"));      
  
                        stream.Close();    
  
                        TabFind = null;    
  
                        FindRow = null;    
  
//这里不需要再继续接受后继数据包了,跳出当前循环体。    
  
                        continue;    
  
                    }    
  
                    //请求添加好友    
  
                    if (_str.StartsWith("Find::AddFriendAsk"))    
  
                    {    
  
                        string UserName = _str.Substring("Find::AddFriendAsk".Length, _str.Length - "Find::AddFriendAsk".Length);    
  
                        //通过转发表查找接收方的套接字    
  
                        if (_transmit_tb.Count != 0 && _transmit_tb.ContainsKey(UserName))    
  
                        {    
  
                            Socket receiverSkt = _transmit_tb[UserName] as Socket;    
  
                            receiverSkt.Send(Encoding.Unicode.GetBytes("Find::AddFriendAsk" + obj as string));    
  
                        }    
  
                        //这里不需要再继续接受后继数据包了,跳出当前循环体。    
  
                        continue;    
  
                    }    
  
                    //回复答应添加好友    
  
                    if (_str.StartsWith("Find::AddFriendYes"))    
  
                    {    
  
                        string UserName = _str.Substring("Find::AddFriendYes".Length, _str.Length - "Find::AddFriendYes".Length);    
  
                      //// 保存数据    
  
                        DataTable TabmyFriend = new DataTable() ;    
  
                        //保存该用户    
  
                        TabmyFriend.ReadXml(MyPath + "\\UserFriend\\" +  obj as string + ".xml");    
  
                        DataRow newRow = TabmyFriend.NewRow();    
  
                        newRow["UserName"] = UserName;    
  
                        TabmyFriend.Rows.Add(newRow);    
  
                        TabmyFriend.WriteXml(MyPath + "\\UserFriend\\" + obj as string + ".xml", XmlWriteMode.WriteSchema, false);    
  
                        //保存其好友    
  
                        TabmyFriend = new DataTable();    
  
                        TabmyFriend.ReadXml(MyPath + "\\UserFriend\\" + UserName + ".xml");    
  
                        DataRow newRow1 = TabmyFriend.NewRow();    
  
                        newRow1["UserName"] = obj as string;    
  
                        TabmyFriend.Rows.Add(newRow1);    
  
                        TabmyFriend.WriteXml(MyPath + "\\UserFriend\\" + UserName + ".xml", XmlWriteMode.WriteSchema, false);    
  
                        TabmyFriend = null;    
  
              //更新好友列表    
  
                        SerializeFriendList(obj, clientSkt);    
  
上面发了服务器端,没发客户端,现在补上!不知道写的好不好,见笑了    
  
C# code    
  
public partial class Form1 : Form    
  
    {    
  
        private TcpClient client;    
  
        private bool isExit = false;    
  
        private NetworkStream networkStream;    
  
        private EventWaitHandle allDone = new EventWaitHandle(false, EventResetMode.ManualReset);   
 
        #region 用于一个线程操作另一个线程的控件    
  
        private delegate void SetListBoxCallback(string str);    
  
        private SetListBoxCallback setListBoxCallBack;    
  
        private delegate void SetRichTextBoxCallback(string str);    
  
        private SetRichTextBoxCallback setRichTextBoxCallBack;   
 
        #endregion    
  
        public Form1()    
  
        {    
  
            InitializeComponent();    
  
            listBoxStatus.HorizontalScrollbar = true;    
  
            setListBoxCallBack = new SetListBoxCallback(SetListBox);    
  
            setRichTextBoxCallBack = new SetRichTextBoxCallback(SetReceiveText);    
  
        }    
  
        //状态显示    
  
        private void SetListBox(string str)    
  
        {    
  
            listBoxStatus.Items.Add(str);    
  
            listBoxStatus.SelectedIndex = listBoxStatus.Items.Count - 1;    
  
            listBoxStatus.ClearSelected();    
  
        }    
  
        //接收客户端信息    
  
        private void SetReceiveText(string str)    
  
        {    
  
            richTextBoxReceive.AppendText(str);    
  
        }    
  
        //连接服务器....    
  
        private void buttonConnet_Click(object sender, EventArgs e)    
  
        {    
  
            client = new TcpClient(AddressFamily.InterNetwork);    
  
            //得到服务器IP    
  
            IPAddress ip= IPAddress.Parse("127.0.0.1");    
  
            //创建一个委托,并知名在异步操作完成时执行的方法    
  
            AsyncCallback callback = new AsyncCallback(RequestCallBack);    
  
            allDone.Reset();    
  
            client.BeginConnect(ip, 7100, RequestCallBack, client);    
  
        }    
  
        private void RequestCallBack(IAsyncResult ar)    
  
        {    
  
            allDone.Set();    
  
            try    
  
            {    
  
                client = (TcpClient)ar.AsyncState;    
  
                client.EndConnect(ar);    
  
                listBoxStatus.Invoke(setListBoxCallBack, string.Format("与服务器{0}连接成功", client.Client.RemoteEndPoint));    
  
                networkStream = client.GetStream();    
  
                ReadObject readObject = new ReadObject(networkStream, client.ReceiveBufferSize);    
  
                networkStream.BeginRead(readObject.bytes, 0, readObject.bytes.Length, ReadCallBack, readObject);    
  
            }    
  
            catch (Exception e1)    
  
            {    
  
                listBoxStatus.Invoke(setListBoxCallBack, e1.Message);    
  
                return;    
  
            }    
  
        }    
  
        //异步操作完成时执行的回调调用的方法    
  
        private void ReadCallBack(IAsyncResult ar)    
  
        {    
  
            try    
  
            {    
  
                ReadObject ro = (ReadObject)ar.AsyncState;    
  
                int count = ro.netStream.EndRead(ar);    
  
                richTextBoxReceive.Invoke(setRichTextBoxCallBack, System.Text.Encoding.UTF8.GetString(ro.bytes, 0, count));    
  
                if (isExit == false)    
  
                {    
  
                    ro = new ReadObject(networkStream, client.ReceiveBufferSize);    
  
                    networkStream.BeginRead(ro.bytes, 0, ro.bytes.Length, ReadCallBack, ro);    
  
                }    
  
            }    
  
            catch (Exception e2)    
  
            {    
  
                listBoxStatus.Invoke(setListBoxCallBack, e2.Message);    
  
                return;    
  
            }    
  
        }    
  
        //发送数据    
  
        private void SendString(string str)    
  
        {    
  
            try    
  
            {    
  
                byte[] by = System.Text.Encoding.UTF8.GetBytes(str+"\r\n");    
  
                networkStream.BeginWrite(by, 0, by.Length, new AsyncCallback(SendCallBack), networkStream);    
  
                networkStream.Flush();    
  
            }catch(Exception e3){    
  
                listBoxStatus.Invoke(setListBoxCallBack, e3.Message);    
  
                return;    
  
            }    
  
        }    
  
        //发送数据回调的方法    
  
        private void SendCallBack(IAsyncResult ar)    
  
        {    
  
            try    
  
            {    
  
                networkStream.EndWrite(ar);    
  
            }    
  
            catch (Exception e4)    
  
            {    
  
                listBoxStatus.Invoke(setListBoxCallBack, e4.Message);    
  
                return;    
  
            }    
  
        }    
  
        private void buttonSend_Click(object sender, EventArgs e)    
  
        {    
  
            SendString(richTextBoxSend.Text);    
  
            richTextBoxSend.Clear();    
  
        }    
  
        private void Form1_FormClosing(object sender, FormClosingEventArgs e)    
  
        {    
  
            isExit = true;    
  
            allDone.Set();    
  
        }    
  
    }   

 

<!--EndFragment-->
分享到:
评论

相关推荐

    TCP.UDP_gaojibiancheng.rar_TCP-UDP_c# tcp/udp_tcp/udp_visual c

    在C#和Visual C++中,可以使用.NET Framework或Winsock库来实现TCP通信。 UDP(用户数据报协议)则是一种无连接的、不可靠的、基于数据报的传输层协议。UDP不保证数据包的顺序、完整性和可靠性,因此它更适合实时性...

    TCP_UDP.rar_C# udp_TCP UDp_UDP_tcp_网络原理实验

    3. 对于UDP通信,使用`UdpClient`类发送和接收数据报文,无需建立连接,只需指定目标IP地址和端口号。 4. 数据的编码和解码,通常使用ASCII或Unicode编码将字符串转换为字节流进行网络传输。 5. 多线程或异步编程,...

    TCP和UDP通信代码实现

    在C#中,可以使用System.Net.Sockets命名空间中的TcpClient和TcpListener类来实现TCP通信。 首先,创建一个TcpListener实例,设置监听的IP地址和端口号,然后调用Start方法开始监听。当有客户端连接时,...

    C# Socket TCP和UDP报文及端口测试工具的开发(提供源码)万能超好测试工具

    在IT行业中,网络通信是至关重要的一个领域,而C#作为一种强大的编程语言,提供了丰富的库来支持网络编程,其中Socket是实现TCP和UDP通信的基础组件。本教程将深入讲解如何利用C#开发一个通用的Socket测试工具,涵盖...

    tcp通信调试助手

    总的来说,TCP通信调试助手是一个实用的工具,它结合了TCP和UDP这两种常见的网络通信协议,并提供了C#源码供学习和参考。通过这个工具,开发者可以加深对网络协议的理解,提高其在实际项目中的应用水平。无论是用于...

    C++UDP通讯类(兼容window和linux)

    总之,这个“C++ UDP通讯类(兼容window和linux)”提供了一种简洁的方式来处理跨平台的UDP通信,减少了开发者在不同操作系统之间移植代码的工作量,提高了开发效率。其详细的注释和测试可用性也体现了作者对代码可...

    tcp、udp网络编程

    网络编程是现代软件开发的重要组成部分,掌握TCP和UDP的基本原理及其在C#中的应用,对于构建高效、可靠的网络应用程序至关重要。无论是实现客户端还是服务器端的功能,理解并合理运用网络协议,都是提高软件性能和...

    UDP资料及其如何实现的例子

    与TCP相比,UDP的主要差异在于它不提供像TCP那样的确认机制和重传机制。TCP通过序列号、确认应答和重传策略确保数据的可靠传输,而UDP则没有这些保障。这意味着UDP在数据丢失或乱序时不会进行修复,而是直接将数据...

    c# socket开发

    TCP通信通常涉及以下步骤: 1. 创建Socket实例。 2. 设置Socket属性,如ProtocolType和AddressFamily。 3. 对于服务器端,调用Bind()绑定本地端口,然后Listen()监听连接请求。 4. 对于客户端,调用Connect()连接到...

    [源码]C#做的局域网Ping和消息发送程序

    5. **UDP或TCP通信**:消息发送部分可能使用了UDP或TCP协议。UDP是无连接的,速度快但不保证数据的可靠传输;TCP则是面向连接的,保证数据的顺序和完整性,但相对慢一些。根据需求,开发者可能会选择更适合局域网...

    UdpTcpAsciiCmd.rar

    在实际应用中,开发者可以利用“UdpTcpAsciiCmd”来验证网络通信的正确性,测试不同网络环境下的性能差异,或者作为学习TCP和UDP协议的实践平台。通过阅读和分析源代码,可以加深对网络编程的理解,特别是C#中Socket...

    一本很好的C#网络编程书籍

    书中可能详细讲解了TCP和UDP协议的工作原理,以及如何使用C#的Socket类进行编程。TCP是一种面向连接的协议,提供可靠的数据传输,而UDP则是一种无连接的协议,适合于实时性要求高的应用。理解这两种协议的差异和应用...

    欧姆龙NJ系列FINS通讯.7z

    5. **TCP与UDP的区别**:理解两者在通信特性上的差异,根据实际需求选择合适的通信方式。 6. **安全考虑**:由于FINS通信可能涉及工业控制系统的操作,因此必须注意网络安全,避免未经授权的访问或攻击。 7. **...

    基于C#的即时通讯客户端源码.zip

    源码可能使用Socket进行TCP或UDP通信,实现客户端与服务器的连接和数据传输。 2. **多线程**:为了实现即时通讯的并发性,源码可能使用C#的Thread类或Task Parallel Library(TPL)进行多线程处理,确保消息的即时...

    点对点聊天

    这个软件的主要目的是作为一个学习工具,帮助开发者理解如何在C#中实现TCP和UDP通信。通过查看源代码,学习者可以了解如何创建套接字、监听端口、发送和接收数据等关键步骤。 在这个项目中,开发者可能创建了两个...

    SocketTool.rar

    SocketTool工具使用验证.jpg很可能包含了如何启动和使用SocketTool.exe的步骤,包括如何配置TCP连接和UDP通信,如何查看和解析接收到的数据,以及如何发送数据。q签到128.txt可能是使用该工具进行特定操作(如定时...

    C# 源码(很多的源码)

    C#中的System.Net.Sockets命名空间提供了套接字相关的类,如Socket,可以用于创建TCP或UDP连接,实现客户端-服务器通信,是网络应用开发的基础。 此外,压缩包中的其他子文件夹也包含了一些关键主题: - **...

    C#网络应用编程[第2版第3版源码和ppt]

    1. **网络基础**:理解TCP/IP协议栈,包括IP、TCP、UDP等协议的工作原理,以及它们在网络通信中的角色。 2. **套接字编程**:学习如何使用C#的System.Net.Sockets命名空间,创建和管理套接字,实现客户端-服务器...

    《C#网络应用高级编程》 课件下载.rar.

    学习如何创建和管理套接字,进行TCP/IP或UDP通信,是构建网络应用的基本技能。 6. Web服务:包括SOAP和RESTful服务,是现代网络应用的重要组成部分。理解如何使用C#创建和消费这些服务,对于构建分布式系统至关重要...

    C#网络应用编程

    2. **网络通信基础**:学习TCP/IP协议族,包括TCP、UDP、HTTP、HTTPS等常用协议的工作原理,理解它们在网络数据传输中的角色。此外,还需要了解套接字(Socket)编程,它是C#进行低级别网络通信的基础。 3. **.NET ...

Global site tag (gtag.js) - Google Analytics