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

2016-08-20 11:07:28来源:http://wengyuli.blog.51cto.com/44136/587562作者:wengyuli人点击


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


整体效果是





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


代码

publicclassUserSocket
{
publicstringUserName{set;get;}
publicstringPartnerName{set;get;}
publicstringMessage{set;get;}
publicDateTimeStoreTime{set;get;}
}



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


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


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


代码

byte[]bytData=newbyte[1024];
intreceivedLength=client.Receive(bytData);
stringstrReceive=System.Text.Encoding.UTF8.GetString(bytData,0,receivedLength);

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




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


代码

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



关键代码:


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



privateSocketclientSocket=null;


及远程通信的IP和端口



privateconststringSERVER_IP="127.0.0.1";
privateconstintSERVER_PORT=4530;

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


代码

clientSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
SocketAsyncEventArgssocketEventArg=newSocketAsyncEventArgs()
{
RemoteEndPoint=newIPEndPoint(IPAddress.Parse(SERVER_IP),SERVER_PORT)
};
socketEventArg.Completed+=newEventHandler<SocketAsyncEventArgs>(socketEventArg_Completed);
clientSocket.ConnectAsync(socketEventArg);



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


代码

//连接成功后开始发送
voidsocketEventArg_Completed(objectsender,SocketAsyncEventArgse)
{
if(e.SocketError==SocketError.Success)
{
//AddText("已连接服务器!");
stringstrSend=USERNAME+"-"+PARTNERNAME+"-"+MESSAGE;
byte[]bytSend=Encoding.UTF8.GetBytes(strSend);
SocketAsyncEventArgssocketArg=newSocketAsyncEventArgs();
socketArg.Completed+=newEventHandler<SocketAsyncEventArgs>(socketArg_Completed);
socketArg.SetBuffer(bytSend,0,bytSend.Length);
clientSocket.SendAsync(socketArg);
//AddText("向服务器发送信息...");
}
}



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


代码

voidsocketArg_Completed(objectsender,SocketAsyncEventArgse)
{
//发送成功
if(e.SocketError==SocketError.Success)
{
AddText("已经将自己的IP和聊天对象发送到服务器");
}
timer=newTimer(newTimerCallback(StartReceive),null,500,1000);
}



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


代码

voidStartReceive(objecto)
{
byte[]byteReceive=newbyte[102400];
SocketAsyncEventArgssocketReceiveArg=newSocketAsyncEventArgs();
socketReceiveArg.Completed+=newEventHandler<SocketAsyncEventArgs>(socketReceiveArg_Completed);
socketReceiveArg.SetBuffer(byteReceive,0,byteReceive.Length);
clientSocket.ReceiveAsync(socketReceiveArg);
}
voidsocketReceiveArg_Completed(objectsender,SocketAsyncEventArgse)
{
if(e.SocketError==SocketError.Success)
{
byte[]byteReceive=e.Buffer;
stringstrText=System.Text.Encoding.UTF8.GetString(byteReceive,0,byteReceive.Length);
AddText("成功接收到服务器回传的消息"+strText);
}
}


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


服务端的监听

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


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




privateconststringSERVER_IP="127.0.0.1";
privateconstintSERVER_PORT=4530;
staticSocketlistener;


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


代码

#regionStartThePolicyServer
PolicySocketServerStartPolicyServer=newPolicySocketServer();
Threadth=newThread(newThreadStart(StartPolicyServer.StartSocketServer));
th.IsBackground=true;
th.Start();
#endregion



然后开始监听


代码

IPEndPointlocalEndPoint=newIPEndPoint(IPAddress.Parse(SERVER_IP),SERVER_PORT);
listener=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
listener.Bind(localEndPoint);
listener.Listen(-1);
Console.WriteLine("等待客户端连接...");
while(true)
{
SocketclientSocket=listener.Accept();
if(clientSocket.Connected)
{
ThreadmyThread=newThread(newParameterizedThreadStart(SocketThread));
myThread.Start(clientSocket);
}
}



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


代码

staticvoidSocketThread(objectclientSocket)
{
try
{
Socketclient=(Socket)clientSocket;
IPEndPointaddress=(IPEndPoint)client.RemoteEndPoint;

byte[]bytData=newbyte[1024];
intreceivedLength=client.Receive(bytData);
stringstrReceive=System.Text.Encoding.UTF8.GetString(bytData,0,receivedLength);

listUserSocket.Add(newUserSocket()
{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()+"】");

UserSocketuserSocket=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
{}
}




最新文章

123

最新摄影

微信扫一扫

第七城市微信公众平台