你得学会并且学得会的Socket编程基础知识

来源:互联网 发布:ps字体下载for mac 编辑:程序博客网 时间:2024/04/30 08:49

这一篇文章,我将图文并茂地介绍Socket编程的基础知识,我相信,如果你按照步骤做完实验,一定可以对Socket编程有更好地理解。

本文源代码,可以通过这里下载 http://files.cnblogs.com/chenxizhang/SocketWorkshop.rar

 

第一步:创建解决方案

image

第二步:创建服务端程序

这里可以选择“Console Application”这个类型,比较方便调试

image

然后编写如下代码,实现服务器的基本功能

using System;using System.Collections.Generic;using System.Linq;using System.Text;//额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer{    class Program    {        /// <summary>        /// Socket Server 演示        /// 作者:陈希章        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            //创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //将该socket绑定到主机上面的某个端口            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx            socket.Bind(new IPEndPoint(IPAddress.Any, 4530));            //启动监听,并且设置一个最大的队列长度            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx            socket.Listen(4);            Console.WriteLine("Server is ready!");            Console.Read();        }    }}

 

现在可以启动调试一下看看效果如何,正常情况下应该会看到一个提示,因为我们需要在TCP 4530端口进行监听,所以防火墙会有提示。

image

点击“Allow access”

image

这样,我们的服务器就可以开始监听了。但是这有什么用呢?是的,没有什么用。

我们还需要为服务器添加一些功能,例如接受传入的请求,给客户端发送消息,或者从客户端接收消息等等

第三步:接受传入的请求

我们需要通过Accept,或者(BeginAccept)来接受传入的请求,请注意下面代码中的红色部分

 

using System;using System.Collections.Generic;using System.Linq;using System.Text;//额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer{    class Program    {        /// <summary>        /// Socket Server 演示        /// 作者:陈希章        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            //创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //将该socket绑定到主机上面的某个端口            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx            socket.Bind(new IPEndPoint(IPAddress.Any, 4530));            //启动监听,并且设置一个最大的队列长度            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx            socket.Listen(4);            //开始接受客户端连接请求            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginaccept.aspx            socket.BeginAccept(new AsyncCallback((ar) =>            {                //这就是客户端的Socket实例,我们后续可以将其保存起来                var client = socket.EndAccept(ar);                //给客户端发送一个欢迎消息                client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at "+DateTime.Now.ToString()));            }), null);            Console.WriteLine("Server is ready!");            Console.Read();        }    }}

 

wow,看起来不错对吧,我们赶紧做一个客户端来测试一下吧

 

第四步:创建客户端

我们还是使用一个Console Application

image

添加如下的代码,并且创建客户端连接

using System;using System.Collections.Generic;using System.Linq;using System.Text;//导入的命名空间using System.Net.Sockets;namespace SocketClient{    class Program    {        /// <summary>        /// Socket Server 演示        /// 作者:陈希章        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            //创建一个Socket            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //连接到指定服务器的指定端口            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.connect.aspx            socket.Connect("localhost", 4530);            Console.WriteLine("connect to the server");            Console.Read();        }    }}

依次选择SocketServer和SocketClient这两个项目,分别将其启动为调试状态(右键菜单,Debug=>Start new instance)

image

我们看到两个程序都工作正常。

但是,在客户端怎么没有收到服务器发过来的消息呢?那是因为,我们没有在客户端提供这方面的功能。

 

第五步:在客户端中实现接受消息的方法

using System;using System.Collections.Generic;using System.Linq;using System.Text;//导入的命名空间using System.Net.Sockets;namespace SocketClient{    class Program    {        /// <summary>        /// Socket Server 演示        /// 作者:陈希章        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            //创建一个Socket            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //连接到指定服务器的指定端口            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.connect.aspx            socket.Connect("localhost", 4530);            //实现接受消息的方法            var buffer = new byte[1024];//设置一个缓冲区,用来保存数据            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginreceive.aspx            socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback((ar) =>            {                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx                var length = socket.EndReceive(ar);                //读取出来消息内容                var message = Encoding.Unicode.GetString(buffer, 0, length);                //显示消息                Console.WriteLine(message);            }), null);            Console.WriteLine("connect to the server");            Console.Read();        }    }}

请注意以上红色的部分,我们用了BeginReceive方法进行异步的消息侦听,如果收到了,我们就打印出来

image

看起来已经实现了我们需求了:服务器给客户端发了一个消息,而客户端也已经收到了。

但是,这远远不够,因为它们之间的通讯不仅仅是一次性的,那么如果服务器要不断地给客户端发消息,例如每隔两秒钟就发送一个消息,如何实现呢?

 

第六步:实现服务器定期向客户端发消息

using System;using System.Collections.Generic;using System.Linq;using System.Text;//额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer{    class Program    {        /// <summary>        /// Socket Server 演示        /// 作者:陈希章        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            //创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //将该socket绑定到主机上面的某个端口            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx            socket.Bind(new IPEndPoint(IPAddress.Any, 4530));            //启动监听,并且设置一个最大的队列长度            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx            socket.Listen(4);            //开始接受客户端连接请求            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginaccept.aspx            socket.BeginAccept(new AsyncCallback((ar) =>            {                //这就是客户端的Socket实例,我们后续可以将其保存起来                var client = socket.EndAccept(ar);                //给客户端发送一个欢迎消息                client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at "+DateTime.Now.ToString()));                //实现每隔两秒钟给服务器发一个消息                //这里我们使用了一个定时器                var timer = new System.Timers.Timer();                timer.Interval = 2000D;                timer.Enabled = true;                timer.Elapsed += (o, a) =>                {                    client.Send(Encoding.Unicode.GetBytes("Message from server at " +DateTime.Now.ToString()));                };                timer.Start();            }), null);            Console.WriteLine("Server is ready!");            Console.Read();        }    }}

 

我们还要实现在客户端一直监听消息的机制,而不是一次性接收.请注意下面红色的部分

 

using System;using System.Collections.Generic;using System.Linq;using System.Text;//导入的命名空间using System.Net.Sockets;namespace SocketClient{    class Program    {        /// <summary>        /// Socket Server 演示        /// 作者:陈希章        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            //创建一个Socket            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //连接到指定服务器的指定端口            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.connect.aspx            socket.Connect("localhost", 4530);            Console.WriteLine("connect to the server");            //实现接受消息的方法            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginreceive.aspx            socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage),socket);            Console.Read();        }        static byte[] buffer = new byte[1024];        public static void ReceiveMessage(IAsyncResult ar)        {            try            {                var socket = ar.AsyncState as Socket;                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx                var length = socket.EndReceive(ar);                //读取出来消息内容                var message = Encoding.Unicode.GetString(buffer, 0, length);                //显示消息                Console.WriteLine(message);                //接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息了)                socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);            }            catch(Exception ex){                Console.WriteLine(ex.Message);            }        }    }}

重新调试起来,看起来的效果如下图所示

image

我们继续做下面的实验,一步一步地研究Socket通讯中可能遇到的一些问题

请先关闭掉客户端这个程序,而不要关闭服务端程序,这时会发现一个错误

image

这个错误很容易理解,因为客户端已经关闭,也就是客户端那个Socket已经不存在了,服务器还继续向它发送消息当然会出错。所以,从可靠性方面的考虑,我们必须在发送消息之前检测Socket的活动状态

 

第七步:检测客户端的活动状态

using System;using System.Collections.Generic;using System.Linq;using System.Text;//额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer{    class Program    {        /// <summary>        /// Socket Server 演示        /// 作者:陈希章        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            //创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //将该socket绑定到主机上面的某个端口            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx            socket.Bind(new IPEndPoint(IPAddress.Any, 4530));            //启动监听,并且设置一个最大的队列长度            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx            socket.Listen(4);            //开始接受客户端连接请求            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginaccept.aspx            socket.BeginAccept(new AsyncCallback((ar) =>            {                //这就是客户端的Socket实例,我们后续可以将其保存起来                var client = socket.EndAccept(ar);                //给客户端发送一个欢迎消息                client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at "+DateTime.Now.ToString()));                //实现每隔两秒钟给服务器发一个消息                //这里我们使用了一个定时器                var timer = new System.Timers.Timer();                timer.Interval = 2000D;                timer.Enabled = true;                timer.Elapsed += (o, a) =>                {                    //检测客户端Socket的状态                    if(client.Connected)                    {                        try                        {                            client.Send(Encoding.Unicode.GetBytes("Message from server at " + DateTime.Now.ToString()));                        }                        catch(SocketException ex)                        {                            Console.WriteLine(ex.Message);                        }                    }                    else                    {                        timer.Stop();                        timer.Enabled = false;                        Console.WriteLine("Client is disconnected, the timer is stop.");                    }                };                timer.Start();            }), null);            Console.WriteLine("Server is ready!");            Console.Read();        }    }}

上面代码的逻辑很清楚,但有时候还是会触发那个SocketException。为什么呢?这是因为我们的Timer是每隔两秒钟检查一次,那么就很可能有一种情况,我们检查的时候,它还是连接状态,消息发出去之后,它断开了。这种情况肯定是存在的。所以要用Try..catch的结构

 

目前我们实现的场景很简单,服务器只管发消息,客户端只管收消息。但实际工作中,可能希望服务器和客户端都能收发消息。请看下一节

 

第八步:实现双向收发消息

先看服务端的修改

 

using System;using System.Collections.Generic;using System.Linq;using System.Text;//额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer{    class Program    {        /// <summary>        /// Socket Server 演示        /// 作者:陈希章        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            //创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //将该socket绑定到主机上面的某个端口            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx            socket.Bind(new IPEndPoint(IPAddress.Any, 4530));            //启动监听,并且设置一个最大的队列长度            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx            socket.Listen(4);            //开始接受客户端连接请求            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginaccept.aspx            socket.BeginAccept(new AsyncCallback((ar) =>            {                //这就是客户端的Socket实例,我们后续可以将其保存起来                var client = socket.EndAccept(ar);                //给客户端发送一个欢迎消息                client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at "+DateTime.Now.ToString()));                //实现每隔两秒钟给服务器发一个消息                //这里我们使用了一个定时器                var timer = new System.Timers.Timer();                timer.Interval = 2000D;                timer.Enabled = true;                timer.Elapsed += (o, a) =>                {                    //检测客户端Socket的状态                    if(client.Connected)                    {                        try                        {                            client.Send(Encoding.Unicode.GetBytes("Message from server at " + DateTime.Now.ToString()));                        }                        catch(SocketException ex)                        {                            Console.WriteLine(ex.Message);                        }                    }                    else                    {                        timer.Stop();                        timer.Enabled = false;                        Console.WriteLine("Client is disconnected, the timer is stop.");                    }                };                timer.Start();                //接收客户端的消息(这个和在客户端实现的方式是一样的)                client.BeginReceive(buffer,0,buffer.Length,SocketFlags.None,new AsyncCallback(ReceiveMessage),client);            }), null);            Console.WriteLine("Server is ready!");            Console.Read();        }        static byte[] buffer = new byte[1024];        public static void ReceiveMessage(IAsyncResult ar)        {            try            {                var socket = ar.AsyncState as Socket;                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx                var length = socket.EndReceive(ar);                //读取出来消息内容                var message = Encoding.Unicode.GetString(buffer, 0, length);                //显示消息                Console.WriteLine(message);                //接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息了)                socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);            }            catch(Exception ex){                Console.WriteLine(ex.Message);            }        }    }}

可以看出来,为了让服务器可以接受消息,其实并不需要什么特别的设计,与客户端接受消息其实可以是一样的

 

再来看看客户端的修改

using System;using System.Collections.Generic;using System.Linq;using System.Text;//导入的命名空间using System.Net.Sockets;namespace SocketClient{    class Program    {        /// <summary>        /// Socket Server 演示        /// 作者:陈希章        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            //创建一个Socket            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //连接到指定服务器的指定端口            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.connect.aspx            socket.Connect("localhost", 4530);            Console.WriteLine("connect to the server");            //实现接受消息的方法            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginreceive.aspx            socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);            //接受用户输入,将消息发送给服务器端            while(true)            {                var message = "Message from client : " + Console.ReadLine();                var outputBuffer = Encoding.Unicode.GetBytes(message);                socket.BeginSend(outputBuffer, 0, outputBuffer.Length, SocketFlags.None, null, null);            }        }        static byte[] buffer = new byte[1024];        public static void ReceiveMessage(IAsyncResult ar)        {            try            {                var socket = ar.AsyncState as Socket;                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx                var length = socket.EndReceive(ar);                //读取出来消息内容                var message = Encoding.Unicode.GetString(buffer, 0, length);                //显示消息                Console.WriteLine(message);                //接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息了)                socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);            }            catch(Exception ex)            {                Console.WriteLine(ex.Message);            }        }    }}

我在这里做了一个死循环,用户可以不断地输入,这些消息会被发送给服务器。如下图所示

image

【备注】因为服务器每隔两秒钟会发送新消息过来,所以在输入的时候,动作要稍快一点啦

 

本文最后探讨一个问题,就是如何让我们的服务器可以支持多个客户端

 

第九步:支持多个客户端

这个步骤只需要修改服务端程序即可

using System;using System.Collections.Generic;using System.Linq;using System.Text;//额外导入的两个命名空间using System.Net.Sockets;using System.Net;namespace SocketServer{    class Program    {        /// <summary>        /// Socket Server 演示        /// 作者:陈希章        /// </summary>        /// <param name="args"></param>        static void Main(string[] args)        {            //创建一个新的Socket,这里我们使用最常用的基于TCP的Stream Socket(流式套接字)            var socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);            //将该socket绑定到主机上面的某个端口            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.bind.aspx            socket.Bind(new IPEndPoint(IPAddress.Any, 4530));            //启动监听,并且设置一个最大的队列长度            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.listen(v=VS.100).aspx            socket.Listen(4);            //开始接受客户端连接请求            //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.beginaccept.aspx            socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);            Console.WriteLine("Server is ready!");            Console.Read();        }        public static void ClientAccepted(IAsyncResult ar)        {            var socket = ar.AsyncState as Socket;            //这就是客户端的Socket实例,我们后续可以将其保存起来            var client = socket.EndAccept(ar);            //给客户端发送一个欢迎消息            client.Send(Encoding.Unicode.GetBytes("Hi there, I accept you request at " + DateTime.Now.ToString()));            //实现每隔两秒钟给服务器发一个消息            //这里我们使用了一个定时器            var timer = new System.Timers.Timer();            timer.Interval = 2000D;            timer.Enabled = true;            timer.Elapsed += (o, a) =>            {                //检测客户端Socket的状态                if(client.Connected)                {                    try                    {                        client.Send(Encoding.Unicode.GetBytes("Message from server at " + DateTime.Now.ToString()));                    }                    catch(SocketException ex)                    {                        Console.WriteLine(ex.Message);                    }                }                else                {                    timer.Stop();                    timer.Enabled = false;                    Console.WriteLine("Client is disconnected, the timer is stop.");                }            };            timer.Start();            //接收客户端的消息(这个和在客户端实现的方式是一样的)            client.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), client);            //准备接受下一个客户端请求            socket.BeginAccept(new AsyncCallback(ClientAccepted), socket);        }        static byte[] buffer = new byte[1024];        public static void ReceiveMessage(IAsyncResult ar)        {            try            {                var socket = ar.AsyncState as Socket;                //方法参考:http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket.endreceive.aspx                var length = socket.EndReceive(ar);                //读取出来消息内容                var message = Encoding.Unicode.GetString(buffer, 0, length);                //显示消息                Console.WriteLine(message);                //接收下一个消息(因为这是一个递归的调用,所以这样就可以一直接收消息了)                socket.BeginReceive(buffer, 0, buffer.Length, SocketFlags.None, new AsyncCallback(ReceiveMessage), socket);            }            catch(Exception ex){                Console.WriteLine(ex.Message);            }        }    }}

最后调试起来看到的效果如下图

image

 

本文源代码,可以通过这里下载 http://files.cnblogs.com/chenxizhang/SocketWorkshop.rar

分类: Microsoft .NET
绿色通道: 好文要顶 关注我 收藏该文与我联系 
陈希章
关注 - 2
粉丝 - 1001
荣誉:推荐博客
+加关注
29
1
(请您对文章做出评价)
« 上一篇:在Silverlight中对多个异步任务的调用
» 下一篇:你得学会并且学得会的Socket编程基础知识(续)——Silverlight客户端

posted on 2011-09-10 09:25 陈希章 阅读(8791) 评论(68) 编辑 收藏

12

评论

#19楼 2011-09-10 23:31 Jeffrey Zhao  

都没处理异常啊,一旦异常就程序退出了,而加上异常处理程序就麻烦了……
支持(0)反对(0)
  

#20楼 2011-09-10 23:44 bobo2012  

谢谢楼主的分享,收益匪浅。

并期待羽之的分享……
支持(0)反对(0)
  

#21楼[楼主2011-09-10 23:45 陈希章  

@Jeffrey Zhao
呵呵,是的,这篇只是一个通俗的例子,还有很多细节可以处理
支持(0)反对(0)
  

#22楼 2011-09-11 00:34 bobo2012  

//读取出来消息内容
var message = Encoding.Unicode.GetString(buffer, 0, length);

老师:为什么这个length,编译报错,需要类型转换才OK。
支持(0)反对(0)
  

#23楼 2011-09-11 02:40 小赖同学  

mark
支持(0)反对(0)
  

#24楼[楼主2011-09-11 08:40 陈希章  

引用bobo2012:
//读取出来消息内容
var message = Encoding.Unicode.GetString(buffer, 0, length);

老师:为什么这个length,编译报错,需要类型转换才OK。

应该不会吧,我这边没有重现你的问题呢
支持(0)反对(0)
  

#25楼 2011-09-11 09:18 小雨点软件  

写的一点都不好,对于新手他怎么知道什么叫套接字?套接字就是一个插座,客户端就是电视,服务器就是电源,它们的连接是建立在220V市电的基础上的,没有电也就谈不到交换数据显示电视剧了。

套接字是socket的中文翻译,翻译的不好(translator肯定是不会翻译,写了一个牛X的词连自己都不明白什么意思),让我翻译我就翻译成“插座”,插座就是一个“连接”,连接电视(customer)和电视台(server),但是连接必须建立在有电(tcp/ip,也就是udp、tcp)的情况下
支持(0)反对(0)
  

#26楼 2011-09-12 12:54 jemmy Liu  

挺好 可惜是C#的 不过思想还是值得称赞的 楼主的VS开发环境背景色是怎么配置的啊 我之前试过没成功
支持(0)反对(0)
  

#27楼[楼主2011-09-12 14:28 陈希章  

引用jemmy Liu:挺好 可惜是C#的 不过思想还是值得称赞的 楼主的VS开发环境背景色是怎么配置的啊 我之前试过没成功

visual studio 样式表,我用的是这个 
http://www.cnblogs.com/walkdan/archive/2006/04/10/370931.html
支持(0)反对(0)
  

#28楼[楼主2011-09-12 14:28 陈希章  

@jemmy Liu
其实语言不是特别难的,你看懂了之后转换为其他语言也很容易
支持(0)反对(0)
  

#29楼 2011-09-12 14:52 jemmy Liu  

@陈希章
恩 收到 感谢 希望楼主有什么好的想法一起分享探讨 没准哪天出本书了呢 呵呵
支持(0)反对(0)
  

#30楼 2011-09-12 22:42 老李飞刀  

Socket 编程实例,

带自定义消息包

http://www.cnblogs.com/atomsoft/archive/2008/08/26/1276290.html
支持(0)反对(0)
  

#31楼 2011-09-13 13:44 toEverybody  

不知Socket在Net4.0中有没有新增功能,讲下这方面的就好了
支持(0)反对(0)
  

#32楼[楼主2011-09-13 19:39 陈希章  

引用toEverybody:不知Socket在Net4.0中有没有新增功能,讲下这方面的就好了

我没有发现有新增功能,其实我觉得socket技术和架构其实已经很成熟,很完善了
支持(0)反对(0)
  

#33楼[楼主2011-09-13 19:40 陈希章  

@老李飞刀
看了你的文章,个人建议文章增加可阅读性
支持(0)反对(0)
  

#34楼 2011-09-13 21:37 老李飞刀  

@陈希章
是的,我没有详细的写过程,

需要有一些基础socket 编程经验才看得懂。

最近在研究一些socket 的开源项目

准备用socket 实现 http 协议
支持(0)反对(0)
  

#35楼[楼主2011-09-14 08:34 陈希章  

@老李飞刀
支持,欢迎有机会分享分享
支持(0)反对(0)
  

#36楼 2011-09-14 12:34 6572789  

谢谢分析,以后好好学习
支持(0)反对(0)
  

#37楼 2011-09-14 17:14 黑择明  

很不错的基础,分享有心了。
支持(0)反对(0)
  

#38楼 2011-09-15 17:00 走过留痕  

楼主写的很好,辛苦了。谢谢分享。
支持(0)反对(0)
  

#39楼 2011-09-15 17:16 无名的新手  

好东西,这就是一个简单的聊天软件了~~:)
支持(0)反对(0)
  

#40楼 2011-09-15 17:22 阿水  

讲的很明白!
支持(0)反对(0)
  

#41楼[楼主2011-09-15 17:57 陈希章  

@黑择明
@无名的新手
@走过留痕
@阿水
@6572789
谢谢支持,大家可在此基础上进一步研究学习
支持(0)反对(0)
  

#42楼 2011-09-15 18:54 樊勇  

楼主的精神值得学习!
支持(0)反对(0)
  

#43楼 2011-09-16 13:55 乔乔lovefreedom  

希章老师总是这么让人感到他的伟大和无私!
支持(0)反对(0)
  

#44楼[楼主2011-09-16 21:59 陈希章  

@乔乔lovefreedom
过奖了阿
支持(0)反对(0)
  

#45楼 2011-09-18 17:38 乔乔lovefreedom  

@陈希章
希章老师,有关软件架构如何搭建的和如何解决软件版本升级带来的软件复杂度的提高,您可以推荐一些资料或者书籍吗,温昱先生的书我看过,但是深度感觉还是不够,因为复杂的系统和简单的系统,对于架构师能力的要求差别太大!
支持(0)反对(0)
  

#46楼 2011-09-19 08:59 张韬  

好文章要顶呀!
支持(0)反对(0)
  

#47楼[楼主2011-09-21 16:47 陈希章  

@乔乔lovefreedom
这里有本书不知道是否对你有帮助
http://apparchguide.codeplex.com/
支持(0)反对(0)
  

#48楼[楼主2011-09-21 16:48 陈希章  

@张韬
呵呵,谢谢啦
支持(0)反对(0)
  

#49楼 2011-09-22 10:30 乔乔lovefreedom  

@陈希章
希章老师,You are my god!这本书很实用!
支持(0)反对(0)
  

#50楼 2011-09-22 11:12 Yayba  

希章老师,您好,我现在也开发一个Socket的程序,程序结构跟您的实例大体差不多,我现在遇到了一个问题,我在接受多个客户端数据的时候,需要按照顺序读取客户端得数据,比如现在有10个客户端每秒不断地向服务器的一个端口中发送数据,服务器端读取客户端数据是没有顺序的,会出现一直接受某几个客户端得数据,另外一些客户端发送了很久服务器才能收到,我希望服务器能按照一定顺序循环接受客户端的数据,比如先接受1客户端,再接受2客户端,3,4。。。。,我想到了用lock加锁同步,虽然一些效果,但还是不能让客户端都按顺序读取。请您有空帮忙指点下,谢谢!
支持(0)反对(0)
  

#51楼[楼主2011-09-22 19:20 陈希章  

引用乔乔lovefreedom:
@陈希章
希章老师,You are my god!这本书很实用!

呵呵,很高兴有帮助,别这么客气啦
支持(0)反对(0)
  

#52楼[楼主2011-09-22 19:22 陈希章  

@Yayba
这个问题,我的看法是这样的:
之所以出现你这样的情况,是因为你在服务端只有一个通道在接收消息,所以势必就会出现阻塞。可以设想一下在一个大超市里面只有一个收银台的情况。

socket.Listen(4);
这个值可以调大一些

那么如何根本解决呢,同样类比一下,你可以在服务端多开几个线程进行处理,这样从理论上说吞吐量就可以加大。

当然,多线程编程就会增加另外的复杂性,线程之间如何避免抢资源等问题。

你先研究一下看看啦
支持(0)反对(0)
  

#53楼 2011-10-09 10:17 茗流  

由于目标机器积极拒绝,无法连接。 192.168.1.105:4545

为什么会出现 目标机器积极拒绝 ? 求解
支持(0)反对(0)
  

#54楼 2011-10-09 10:19 茗流  

namespace SocketClient 

socket.Connect("192.168.1.105", 4545);

如果写成, socket.Connect("localhost", 4545);

就这样的错误:
由于目标机器积极拒绝,无法连接。 127.0.0.1:4545
支持(0)反对(0)
  

#55楼 2011-10-09 11:05 茗流  

解决了, 要双开 ...
支持(0)反对(0)
  

#56楼 2011-10-09 11:48 飘零SUCCEED  

好强悍,因为不懂Socket,所以感觉很强大,一直想学,不知道可不可以从这个例子开始
支持(0)反对(0)
  

#57楼[楼主2011-10-09 17:57 陈希章  

@茗流
很高兴你已解决问题
支持(0)反对(0)
  

#58楼[楼主2011-10-09 17:58 陈希章  

@飘零SUCCEED
我相信可以的
支持(0)反对(0)
  

#59楼 2011-10-09 18:00 茗流  

可不可以 应用到 DataSet 数据库的操作数据上
支持(0)反对(0)
  

#60楼[楼主2011-10-09 18:45 陈希章  

@茗流
理论上肯定可以,但数据库访问有很多现成的技术,例如WCF等
支持(0)反对(0)
  

#61楼 2011-10-09 22:55 茗流  

因为 WCF 有些错误 还不能解决(例如:终结点错误 这些),公司决定用 Socket ...
支持(0)反对(0)
  

#62楼[楼主2011-10-10 00:03 陈希章  

引用茗流:因为 WCF 有些错误 还不能解决(例如:终结点错误 这些),公司决定用 Socket ...

对你们公司的这个决定,我只能笑而不语,呵呵
支持(0)反对(0)
  

#63楼 2011-10-10 09:09 飘零SUCCEED  

@陈希章
谢谢楼主的分享
支持(0)反对(0)
  

#64楼 2011-12-26 15:11 luosong  

谢谢楼主,帮助很大
支持(0)反对(0)
  

#65楼 2012-03-14 12:27 leslie_  

@Jeffrey Zhao
beginxxx xxasync有什么不同嘛?
很多说都是基于iocp模型的,但说法不一。
支持(0)反对(0)
  

#66楼 2013-05-01 18:03 爱易网络  

若是你的网站权重不够高,你随意修正主页版面的话,很有能够会被强权,首要体现为主页快照回档,排名降低,录入增添乃至被K的情况。

  主页要素修正是网站运营傍边的一个常常遇到并且很重要的难题,下面suhu.co说说怎样更改网站三项Title、关键字描绘、网站描绘而不被搜索引擎降权,仅供参阅。

  首要,选好并断定你的网站页面三项(即Title、关键字描绘、网站描绘)吧,这里选网站页面三项有个约束,就是格式是固定的。何为格式固定呢?意思就是得按照你本来的网站现已有的Title、关键字描绘、网站描绘的格式来进行更改,不能随意更改。举个比方,比方我的一个易懂网站的本来的title是:服装出售 服装总署理 服装批发 服装批发电话。后来你的网站在运营过程中,许多都是出售童装的,而你的尚卡网站定位为服装,通过团队评论后发现定位不明晰,需求更高。此刻你能够按照以上格式进行关键字挑选来更改。详细可看:

  1. 若是你的title的格式是每个关键字中是用空格来离隔的,那你就得按照空格来定位,不能更改成“|”或许“,”等其他符号来做分隔符。

  2. 关键字字数要相反。比方以上标题第一个关键是4个字,第二个关键字是5个字,第三个是四个字,第四个是6个字,那你就得按照这个格式来写你的关键字,比方更改成:童装网购 童装批发商 童装署理 童装批发电话 。这样来更改你的title,相反网站的其他两项关键字描绘、网站描绘相反需求这样更改。

  3. 若是你的关键字比本来的多的话,相反适用,需求你按照格式编撰前面的关键字标题后,后边再添加你的需求添加的关键字,比方刚刚现已断定了:童装网购 童装批发商 童装署理 童装批发电话 这样的title,而你还想添加多一些关键字标题,比方还想添加 广州童装批发署理。你能够再以上基础上只能在后边添加,添加后为:童装网购 童装批发商 童装署理 童装批发电话 广州童装批发署理 。不过需求稳重,一同更改那么多能够对搜索引擎不太友爱,主张,先修正后添加。

  4. 拓宽一:若是你的title方式如:服装出售|服装总署理|服装批发|服装批发电话,那就只能更改为:装网购|童装批发商|童装署理|童装批发电话 这样的格式。

  5. 拓宽二:若是你发现之前的你的title第一个关键字是4个字,不能满意你的需求,你想改成六个或许其他字数,那该怎样改呢?联系第二个关键字来写。比方童装网购 童装批发商,一共19个字符,你更改后的关键字也应该为19个字符。第二十个字符有必要跟之前的相反。此抛丸机拓宽风险系数较高,请稳重挑选。

  总结以上,就是更改网页三项的时分只能改字,不能改格式,所以按照以上办法断定了你的格式之后,更新主页即可,更新主页后的保护,若是你的网站更新不规则,那么这几天不要更新了,更主页快照更新了再更新文章,若是你的是每天更新的,那照常,牢记不可大更新!以上办法经测验,格外适用于baidu搜索引擎,相反适用于搜狗和搜搜,Google未测验,稳重参阅www.aiyiweb.com
支持(0)反对(0)
  

#67楼 2013-05-24 11:37 张璇  

太经典了,深入浅出。
支持(0)反对(0)
  

#68楼 2013-06-14 11:23 马哲  

不错,入门级必读。