Socket通讯还是比较实用的,目前研究阶段,demo也存在需要完善的地方。demo中实现了,客户端发送数据给服务端,服务端回复客户端消息。服务端主动给客户端发送消息。先上图看效果:
服务端
界面简单明了
启动
开启监听,准备接受
private void btnStart_Click(object sender, EventArgs e)
{
Thread thread = new Thread(StartListening);
thread.Start();
}
private void StartListening()
{
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
// IPAddress ipAddress = ipHostInfo.AddressList[0];
IPAddress.TryParse(txtIp.Text, out IPAddress ipAddress);
int port = Convert.ToInt32(txtPort.Text);
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, port);
listener = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
while (true)
{
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
}
}
catch (Exception ex)
{
return;
}
}
private void AcceptCallback(IAsyncResult ar)
{
// Get the socket that handles the client request.
//获取处理客户端请求的套字节
listener = (Socket)ar.AsyncState;
handler = listener.EndAccept(ar);
handler.BeginReceive(buffer, 0, BufferSize, 0,
new AsyncCallback(ReadCallback), handler);
}
处理收到的数据,send相当于回复客户端
private void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
handler = (Socket)ar.AsyncState;
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
sb.Append(Encoding.Default.GetString(
buffer, 0, bytesRead));
content = sb.ToString();
if (content.Length > 0)
{
this.Invoke((EventHandler)delegate
{
txtRecive.Text = content;
});
Send(handler, "服务端收到数据");
}
handler.BeginReceive(buffer, 0, BufferSize, 0,
new AsyncCallback(ReadCallback), handler);
}
}
服务端主动发送:
private void btnSend_Click(object sender, EventArgs e)
{
Send(handler, txtSend.Text);
}
/// <summary>
/// 服务端回复客户端
/// </summary>
/// <param name="handler"></param>
/// <param name="data"></param>
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
byte[] byteData = Encoding.Default.GetBytes(data);
// Begin sending the data to the remote device.
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
/// <summary>
/// 发送回到
/// </summary>
/// <param name="ar"></param>
private static void SendCallback(IAsyncResult ar)
{
try
{
Socket handler = (Socket)ar.AsyncState;
int bytesSent = handler.EndSend(ar);
Console.WriteLine("发送 {0} 字节到客户端.", bytesSent);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
客户端
客户端主动连接服务端,并向服务端发送消息
private void StartClient()
{
//绑定端口和地址
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress.TryParse(txtIp.Text, out IPAddress ipAddress);
int port = Convert.ToInt32(txtPort.Text);
IPEndPoint remoteEP = new IPEndPoint(ipAddress, port);
//创建客户端
client = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
//开始连接
IAsyncResult result= client.BeginConnect(remoteEP,
new AsyncCallback(ConnectCallback), client);
}
/// <summary>
/// 连接回调
/// </summary>
/// <param name="ar"></param>
private void ConnectCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
client.EndConnect(ar);
this.Invoke((EventHandler)delegate
{
txtRecive.Text = string.Format("连接成功。。。", client.RemoteEndPoint.ToString());
});
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
发送和接收的函数及回调
private void btnSend_Click(object sender, EventArgs e)
{
Send(client, txtSend.Text);
// sendDone.WaitOne();
Receive(client);
}
/// <summary>
/// 接收服务端消息,
/// 不需要接收,可以不调用
/// </summary>
/// <param name="socket"></param>
private void Receive(object socket)
{
try
{
Socket client = (Socket)socket;
client.BeginReceive(buffer, 0, BufferSize, 0,
new AsyncCallback(ReceiveCallback), client);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
/// <summary>
/// 收到消息的回调
/// </summary>
/// <param name="ar"></param>
private void ReceiveCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
String content = String.Empty;
// Read data from the remote device.
int bytesRead = client.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
sb.Append(Encoding.Default.GetString(buffer, 0, bytesRead));
content = sb.ToString();
// Get the rest of the data.
client.BeginReceive(buffer, 0, BufferSize, 0,
new AsyncCallback(ReceiveCallback), client);
// All the data has arrived; put it in response.
if (content.Length > 0)
{
this.Invoke((EventHandler)delegate
{
txtRecive.AppendText("/r/n" + content);
});
}
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
private void Send(Socket client, string data)
{
byte[] byteData = Encoding.Default.GetBytes(data);
// Begin sending the data to the remote device.
client.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), client);
}
/// <summary>
/// 发送消息回调
/// </summary>
/// <param name="ar"></param>
private void SendCallback(IAsyncResult ar)
{
try
{
Socket client = (Socket)ar.AsyncState;
int bytesSent = client.EndSend(ar);
Console.WriteLine("发送 {0}字节到服务端.", bytesSent);
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
里面有些bug是没有处理的,像服务端断开,客户端重连报错。客户端断开,服务端发送数据失败处理等。
源码下载