异步客户端/服务器通信 C#
Posted
技术标签:
【中文标题】异步客户端/服务器通信 C#【英文标题】:Async Client/Server Communication C# 【发布时间】:2012-12-04 09:54:42 【问题描述】:我正在学习客户端/服务器编程,并且正在制作一个异步客户端/服务器聊天应用程序。
我可以将客户端连接到服务器并发送一条消息,但是我在将相同的消息(仅用于测试目的)发送回客户端时遇到了问题。任何帮助表示赞赏...
客户代码
byte[] dataBuffer = new byte[10];
public AsyncCallback callBack;
public Socket clientSocket;
IAsyncResult ar;
Random rnd=new Random();
private void btnSend_Click(object sender, RoutedEventArgs e)
try
Object objData = txtMessage.Text;
byte[] byData = Encoding.ASCII.GetBytes(objData.ToString());
if (clientSocket != null)
clientSocket.Send(byData);
lbxMessages.Items.Add(txtMessage.Text);
txtMessage.Text = "";
btnSend.IsEnabled = false;
catch(SocketException se)
MessageBox.Show(se.Message);
//SocketPacket CLASS
public class SocketPacket
public Socket thisSocket;
public byte[] dataBuffer = new byte[10];//test no, prevous [1]
//METHODS
private void WaitForData()
try
if (callBack == null)
callBack = new AsyncCallback(OnDataReceived);
SocketPacket sckPack = new SocketPacket();
sckPack.thisSocket = clientSocket;
ar = clientSocket.BeginReceive(sckPack.dataBuffer, 0, sckPack.dataBuffer.Length, SocketFlags.None, callBack, sckPack);
catch(SocketException se)
MessageBox.Show(se.Message);
public void OnDataReceived(IAsyncResult ar)
try
SocketPacket sckID = (SocketPacket)ar.AsyncState;
int iRx = sckID.thisSocket.EndReceive(ar);
char[] chars = new char[iRx + 1];
Decoder d = Encoding.UTF8.GetDecoder();
int charLen = d.GetChars(sckID.dataBuffer, 0, iRx, chars, 0);
String szData = new String(chars);
this.Dispatcher.Invoke((Action)(() =>
lbxMessages.Items.Add(txtMessage.Text + szData);
));
WaitForData();
catch (ObjectDisposedException)
Debugger.Log(0, "1", "\n OnDataRecieved: Socket has been closed\n");
catch(SocketException se)
MessageBox.Show(se.Message);
服务器代码
private void OnClientConnect(IAsyncResult asyncResult)
try
workerSocket[clientCount] = listenSocket.EndAccept(asyncResult);
WaitForData(workerSocket[clientCount]);
++clientCount;
if (clientCount<4)//allow max 3 clients
String str = String.Format("Client # 0 connected", clientCount);
this.Dispatcher.Invoke((Action)(() =>
lbxMessages.Items.Add(str);
lblConnectionStatus.Content =clientCount + " Connected";
));
listenSocket.BeginAccept(OnClientConnect, null);
catch (ObjectDisposedException)
System.Diagnostics.Debugger.Log(0, "1", "\n OnClientConnection: Socket has been closed\n");
catch (SocketException se)
MessageBox.Show(se.Message);
public class SocketPacket
public Socket currentSocket;
public byte[] dataBuffer = new byte[50];//allowing the 50 digist to be sent at once
private void WaitForData(Socket socket)
try
if (workerCallBack == null)
workerCallBack = OnDataReceived;
SocketPacket sckPack = new SocketPacket();
sckPack.currentSocket = socket;
socket.BeginReceive(sckPack.dataBuffer, 0, sckPack.dataBuffer.Length, SocketFlags.None, workerCallBack, sckPack);
catch(SocketException se)
MessageBox.Show(se.Message);
public void OnDataReceived(IAsyncResult asyncResult)
try
SocketPacket socketData = (SocketPacket)asyncResult.AsyncState;
int iRx = 0;
iRx = socketData.currentSocket.EndReceive(asyncResult);
char[] chars = new char[iRx];
Decoder decoder = Encoding.UTF8.GetDecoder();
int charLen = decoder.GetChars(socketData.dataBuffer, 0, iRx, chars, 0);
String receivedData = new String(chars);
this.Dispatcher.Invoke(DispatcherPriority.Normal, (Action)(() => lbxMessages.Items.Add(receivedData)));
//Does not work - does not send same message back to client
//byte[] byData = Encoding.ASCII.GetBytes(receivedData);
//if (listenSocket != null)
//
// listenSocket.Send(byData);
//
WaitForData(socketData.currentSocket);
catch (ObjectDisposedException)
System.Diagnostics.Debugger.Log(0, "1", "\n OnDataRecieved: Socket has been closed\n");
catch (SocketException se)
MessageBox.Show(se.Message);
【问题讨论】:
当你说它不起作用时,你的意思是它根本没有发回任何东西,或者它发送了错误的数据?我注意到您使用了两种不同的编码,您使用 UTF8 解码数据和 ASCII 将其编码回字符串中的字节。 它不会发送任何东西。我收到一条消息说“无法建立连接,因为目标计算机主动拒绝它”。没有意识到我使用了两种不同的编码。我会改变的。 【参考方案1】:您应该使用相同的套接字来发送和接收数据。你在 socketData.currentSocket 上调用 EndReceive,所以你也应该调用 socketData.currentSocket.Send。
在服务器端有两个套接字。一个用于“收听”,您在其上调用accept。客户端连接后,accept 调用会为该客户端连接创建一个套接字,然后您可以使用该套接字为该特定客户端发送和接收数据。
您不使用“侦听”套接字来发送/接收数据。它没有连接到特定的连接。它仅用作接受新客户端连接的一种方式。
见http://msdn.microsoft.com/en-us/library/fx6588te.aspx
【讨论】:
以上是关于异步客户端/服务器通信 C#的主要内容,如果未能解决你的问题,请参考以下文章