在Silverlight中使用Socket进行通信(3)简单的文本聊天工具

简介:

在上一篇的基础上,晚上我又尝试了一下做个聊天工具,有个定时取消息的过程解决不好,明天再研究一下,在这个文本聊天的基础上,稍加扩展就可以进行视频聊天了,下一篇将会做silverlight视频聊天的DEMO.

整体效果是

    

 

还是从服务端说起,服务端做中转消息用,为了模拟聊天情景,服务端简单写了一个实体用来缓存聊天内容 

代码
public   class  UserSocket 
    { 
        
public   string  UserName {  set get ; } 
        
public   string  PartnerName {  set get ; }         
        
public   string  Message {  set get ; } 
        
public  DateTime StoreTime {  set get ; } 
    }

  

然后在主程序中声明一个List<UserSocket>对象存储聊天内容。

static List<UserSocket> listUserSocket = new List<UserSocket>();

当聊天双方给对方发送消息时,可以通过预先设定的字符串格式,比如采用 - 来将发送者,接受者,聊天内容组合起来发送到服务器进行解析和存储。

 代码

byte [] bytData  =   new   byte [ 1024 ]; 
                
int  receivedLength  =  client.Receive(bytData); 
                
string  strReceive  =  System.Text.Encoding.UTF8.GetString(bytData,  0 , receivedLength); 

                listUserSocket.Add(
new  UserSocket() 
                { UserName 
=  strReceive.Split( ' - ' )[ 0 ], 
                    PartnerName 
=  strReceive.Split( ' - ' )[ 1 ], 
                    Message 
=  strReceive.Split( ' - ' )[ 2 ], 
                    StoreTime
= DateTime.Now });

 

 当客户端A定时来服务器请求发给自己的消息时,服务器就会在listUserSocket中查找到发送给A的消息并清除此消息。

 代码

UserSocket userSocket  =  listUserSocket.Where(m  =>  m.PartnerName  ==  strReceive.Split( ' - ' )[ 0 ]).FirstOrDefault(); 
                listUserSocket.RemoveAll(m 
=>  m.PartnerName  ==  strReceive.Split( ' - ' )[ 0 ]);

 

 关键代码:

由于silverlight中没有提供监听socket请求的方法,只能作为客户端跟服务器进行交互,所以在客户端我们可以预先定义一个Socket

 

private   Socket clientSocket  =   null ;  

 及远程通信的IP和端口 

private   const   string  SERVER_IP  =   " 127.0.0.1 "
        
private   const   int  SERVER_PORT  =   4530 ;

 我们可以为这个clientSocket建立起连接 

代码
clientSocket  =   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
            SocketAsyncEventArgs socketEventArg 
=   new  SocketAsyncEventArgs() 
            { 
                RemoteEndPoint 
=   new  IPEndPoint(IPAddress.Parse(SERVER_IP), SERVER_PORT) 
            }; 
            socketEventArg.Completed 
+= new  EventHandler < SocketAsyncEventArgs > (socketEventArg_Completed); 
            clientSocket.ConnectAsync(socketEventArg);

 

鉴于sl的事件处理是异步的,所以 

代码
//  连接成功后 开始发送 
         void  socketEventArg_Completed( object  sender, SocketAsyncEventArgs e) 
        { 
            
if  (e.SocketError  ==  SocketError.Success) 
            { 
                
// AddText("已连接服务器!"); 
                 string  strSend  =  USERNAME + " - " + PARTNERNAME + " - " + MESSAGE; 
                
byte [] bytSend  =  Encoding.UTF8.GetBytes(strSend); 
                SocketAsyncEventArgs socketArg 
=   new  SocketAsyncEventArgs(); 
                socketArg.Completed 
+=   new  EventHandler < SocketAsyncEventArgs > (socketArg_Completed); 
                socketArg.SetBuffer(bytSend, 
0 , bytSend.Length); 
                clientSocket.SendAsync(socketArg); 
                
// AddText("向服务器发送信息...");                
            }            
        }

  

当发送成功后,就可以向服务器取消息啦 

代码
void  socketArg_Completed( object  sender, SocketAsyncEventArgs e) 
        { 
             
// 发送成功 
             if  (e.SocketError  ==  SocketError.Success) 
            { 
                AddText(
" 已经将自己的IP和聊天对象发送到服务器 " ); 
            } 
            timer 
=   new  Timer( new  TimerCallback(StartReceive),  null 500 1000 );            
        }

  

定时取消息的方法,也是异步的 

代码
void  StartReceive( object  o) 
        { 
            
byte [] byteReceive = new   byte [ 102400 ]; 
            SocketAsyncEventArgs socketReceiveArg 
=   new  SocketAsyncEventArgs(); 
            socketReceiveArg.Completed 
+=   new  EventHandler < SocketAsyncEventArgs > (socketReceiveArg_Completed); 
            socketReceiveArg.SetBuffer(byteReceive, 
0 , byteReceive.Length); 
            clientSocket.ReceiveAsync(socketReceiveArg); 
        } 
        
void  socketReceiveArg_Completed( object  sender, SocketAsyncEventArgs e) 
        { 
            
if  (e.SocketError  ==  SocketError.Success) 
            { 
                
byte [] byteReceive  =  e.Buffer; 
                
string  strText  =  System.Text.Encoding.UTF8.GetString(byteReceive,  0 , byteReceive.Length); 
                AddText(
" 成功接收到服务器回传的消息 "   +  strText); 
            } 
        } 

 可以看到,从连接到发送,再到接收,我们用的是一个socket实例来完成的,也就是说在silverlight中只需要连接一次socket就可以顺利进行后续操作了。

服务端的监听

服务端的监听socket 跟客户端的不同,监听是一个socket实例,发送和接收则是另外一个代表客户端的实例。

首先还是需要指定监听IP和端口及使用的Socket

 

private   const   string  SERVER_IP  =   " 127.0.0.1 "
        
private   const   int  SERVER_PORT  =   4530
        
static  Socket listener;

  

同样,也需要进行策略文件的验证 

代码
#region  Start The Policy Server 
                PolicySocketServer StartPolicyServer 
=   new  PolicySocketServer(); 
                Thread th 
=   new  Thread( new  ThreadStart(StartPolicyServer.StartSocketServer)); 
                th.IsBackground 
=   true
                th.Start(); 
                
#endregion

 

 然后开始监听 

代码
IPEndPoint localEndPoint  =   new  IPEndPoint(IPAddress.Parse(SERVER_IP), SERVER_PORT); 
                listener 
=   new  Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 
                listener.Bind(localEndPoint); 
                listener.Listen(
- 1 ); 
                Console.WriteLine(
" 等待客户端连接... " ); 
                
while  ( true
                { 
                    Socket clientSocket 
=  listener.Accept(); 
                    
if  (clientSocket.Connected) 
                    {                     
                        Thread myThread 
=   new  Thread( new  ParameterizedThreadStart(SocketThread)); 
                        myThread.Start(clientSocket); 
                    } 
                } 

 

 当监听到有客户端连接时,就另外开启线程进行处理,这个操作同时也确定了需要多个socket实例进行应答。 

代码
static   void  SocketThread( object  clientSocket)   
        { 
            
try  
            { 
                Socket client 
=  (Socket)clientSocket; 
                IPEndPoint address 
=  (IPEndPoint)client.RemoteEndPoint; 

                
byte [] bytData  =   new   byte [ 1024 ]; 
                
int  receivedLength  =  client.Receive(bytData); 
                
string  strReceive  =  System.Text.Encoding.UTF8.GetString(bytData,  0 , receivedLength); 

                listUserSocket.Add(
new  UserSocket() 
                { UserName 
=  strReceive.Split( ' - ' )[ 0 ], 
                    PartnerName 
=  strReceive.Split( ' - ' )[ 1 ], 
                    Message 
=  strReceive.Split( ' - ' )[ 2 ], 
                    StoreTime
= DateTime.Now }); 
                Console.WriteLine(
" "   +  strReceive.Split( ' - ' )[ 0 +   " 】通过【 "   +  address.Address.ToString()  +   " : "   +  address.Port.ToString()  +   " 】登录了服务器,并给【 "   +  strReceive.Split( ' - ' )[ 1 +   " 】留言如下: " ); 
                Console.WriteLine(strReceive.Split(
' - ' )[ 2 ] + " ,当前服务器消息数量【: " + listUserSocket.Count.ToString() + " " ); 

                UserSocket userSocket 
=  listUserSocket.Where(m  =>  m.PartnerName  ==  strReceive.Split( ' - ' )[ 0 ]).FirstOrDefault(); 
                listUserSocket.RemoveAll(m 
=>  m.PartnerName  ==  strReceive.Split( ' - ' )[ 0 ]); 
                
if  (userSocket  !=   null
                { 
                    client.Send(System.Text.Encoding.UTF8.GetBytes(userSocket.Message)); 
                    Console.WriteLine(
" "   +  userSocket.PartnerName  +   " 】取走了消息【 "   +  userSocket.Message  +   " 】,当前服务器消息数量【: " + listUserSocket.Count.ToString() + " " ); 
                } 
            } 
            
catch  
            {   } 
        } 



     本文转自wengyuli 51CTO博客,原文链接:http://blog.51cto.com/wengyuli/587562,如需转载请自行联系原作者



相关文章
|
11月前
|
网络协议 Unix Linux
# 2个类轻松构建高效Socket通信库
本文介绍了一种通过两个类`EpollEventHandler`和`IEpollEvent`构建高效Socket通信库的方法。该库支持TCP、UDP和Unix域套接字,采用I/O多路复用技术(如epoll),提升并发处理能力。通过抽象基类和具体事件类的设计,简化了API使用,便于开发者快速上手。文章还提供了服务端与客户端的实例代码,展示其在实际项目中的应用效果。此Socket库适应嵌入式环境,功能定制性强,有助于减少外部依赖并提升维护效率。
324 99
# 2个类轻松构建高效Socket通信库
|
Python
python socket 简单通信
python socket 简单通信
208 1
|
11月前
|
网络协议 开发者 Python
Socket如何实现客户端和服务器间的通信
通过上述示例,展示了如何使用Python的Socket模块实现基本的客户端和服务器间的通信。Socket提供了一种简单且强大的方式来建立和管理网络连接,适用于各种网络编程应用。理解和掌握Socket编程,可以帮助开发者构建高效、稳定的网络应用程序。
600 10
|
网络协议 安全 网络安全
网络编程:基于socket的TCP/IP通信。
网络编程:基于socket的TCP/IP通信。
|
11月前
|
JSON 测试技术 网络安全
Apifox工具让我的 Socket.IO 测试效率翻倍
用了 Apifox 测试 Socket.IO 后,我整个人都升级了!不仅操作简单到令人发指,功能还贼全面,真的是 提升开发效率的神器 !
|
Java 流计算
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
230 2
Flink-03 Flink Java 3分钟上手 Stream 给 Flink-02 DataStreamSource Socket写一个测试的工具!
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【10月更文挑战第10天】网络协议定义了机器间通信的标准格式,确保信息准确无损地传输。主要分为两种模型:OSI七层模型与TCP/IP模型。
|
网络协议 Linux 应用服务中间件
Socket通信之网络协议基本原理
【9月更文挑战第14天】网络协议是机器间交流的约定格式,确保信息准确传达。主要模型有OSI七层与TCP/IP模型,通过分层简化复杂网络环境。IP地址全局定位设备,MAC地址则在本地网络中定位。网络分层后,数据包层层封装,经由不同层次协议处理,最终通过Socket系统调用在应用层解析和响应。
|
Java API 开发者
Java网络编程基础与Socket通信实战
Java网络编程基础与Socket通信实战
|
Java 数据格式
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
Java面试题:简述Java Socket编程的基本流程,包括客户端和服务器的创建与通信。
330 0

热门文章

最新文章