在上一篇的基础上,晚上我又尝试了一下做个聊天工具,有个定时取消息的过程解决不好,明天再研究一下,在这个文本聊天的基础上,稍加扩展就可以进行视频聊天了,下一篇将会做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, 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, 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 ServerPolicySocketServer 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, 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, 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 { } } 总结
以上是内存溢出为你收集整理的在Silverlight中使用Socket进行通信(3)简单的文本聊天工具全部内容,希望文章能够帮你解决在Silverlight中使用Socket进行通信(3)简单的文本聊天工具所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)