欢迎光临

木子屋

标题: C#使用Socket发送和接收TCP数据示例(异步版)

作者: dnawo

日期: 2014-08-15 06:37 PM

分类: Win编程

内容: 复制内容到剪贴板 程序代码using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
namespace ConsoleApplication1
{
public class StateObject
{
public Socket workSocket = null;
public byte[] buffer = new byte[1024];
public List<byte> data = new List<byte>();
//public const int BufferSize = 1024;
//public StringBuilder sb = new StringBuilder();
}
/// <summary>
/// 服务端
/// </summary>
public static class Server
{
private static Encoding encode = Encoding.Default;
private static ManualResetEvent acceptDone = new ManualResetEvent(false);
private static ManualResetEvent receiveDone = new ManualResetEvent(false);
private static ManualResetEvent sendDone = new ManualResetEvent(false);
private static byte[] endmark = new byte[] { 0x3C, 0x45, 0x4F, 0x46, 0x3E }; //约定结束符
public static void Listen(int port)
{
Socket listenSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
listenSocket.Bind(new IPEndPoint(IPAddress.Any, port));
listenSocket.Listen(100);
Console.WriteLine("Listen " + port + " ...");
while (true)
{
acceptDone.Reset();
listenSocket.BeginAccept(EndAccept, listenSocket);
acceptDone.WaitOne();
}
}
#region callback methods
private static void EndAccept(IAsyncResult ar)
{
Socket listener = (Socket)ar.AsyncState;
Socket socket = listener.EndAccept(ar);//必须调用EndAccept获取新的Socket对象才可以收发数据
StateObject state = new StateObject();
state.workSocket = socket;
socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, EndReceive, state);
acceptDone.Set();
receiveDone.WaitOne();
}
private static void EndReceive(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket socket = state.workSocket;
int length = socket.EndReceive(ar);
for (int j = 0; j < length; j++)
{
state.data.Add(state.buffer[j]);
}
if (!IsEnd(state.data.ToArray()))
{
socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, EndReceive, state);
}
else
{
if (state.data.Count > 0)
{
string receiveData = encode.GetString(state.data.ToArray(), 0, state.data.Count - endmark.Length);
Console.WriteLine("Receive：" + receiveData);
byte[] responseData = AddEndMark("ok");
socket.BeginSend(responseData, 0, responseData.Length, SocketFlags.None, EndSend, socket);
}
receiveDone.Set();
sendDone.WaitOne();
}
}
private static void EndSend(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState;
socket.EndSend(ar);
DestroySocket(socket);
sendDone.Set();
}
#endregion
#region private methods
private static void DestroySocket(Socket socket)
{
if (socket != null)
{
if (socket.Connected)
{
socket.Shutdown(SocketShutdown.Both);
}
socket.Close();
}
}
public static byte[] AddEndMark(string data)
{
byte[] databytes = encode.GetBytes(data);
byte[] result = new byte[databytes.Length + endmark.Length];
Array.Copy(databytes, 0, result, 0, databytes.Length);
Array.Copy(endmark, 0, result, databytes.Length, endmark.Length);
return result;
}
public static bool IsEnd(byte[] data)
{
bool result = true;
if (data.Length >= endmark.Length)
{
for (int j = 0; j < endmark.Length; j++)
{
if (data[data.Length - 1 - j] != endmark[endmark.Length - 1 - j])
{
result = false;
break;
}
}
}
return result;
}
#endregion
}
/// <summary>
/// 客户端
/// </summary>
public class Client
{
private Encoding encode = Encoding.Default;
private ManualResetEvent connectDone = new ManualResetEvent(false);
private ManualResetEvent receiveDone = new ManualResetEvent(false);
private ManualResetEvent sendDone = new ManualResetEvent(false);
private static byte[] endmark = new byte[] { 0x3C, 0x45, 0x4F, 0x46, 0x3E }; //约定结束符
//event
public delegate void SendCompletedEventHandler(string message);
public event SendCompletedEventHandler SendCompleted;
private void OnSendCompleted(string message)
{
if (SendCompleted != null)
{
SendCompleted(message);
}
}
public void Send(string host, int port, string data)
{
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//1.建立连接
clientSocket.BeginConnect(host, port, EndConnect, clientSocket); //异步不能用Connect方法建立连接
connectDone.WaitOne();
//2.发送数据
byte[] sendData = AddEndMark(data);
clientSocket.BeginSend(sendData, 0, sendData.Length, SocketFlags.None, EndSend, clientSocket);
//Console.WriteLine("Send：" + data);
sendDone.WaitOne();
//3.接收数据
StateObject state = new StateObject();
state.workSocket = clientSocket;
clientSocket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, EndReceive, state);
receiveDone.WaitOne();
DestroySocket(clientSocket);
}
#region callback methods
private void EndConnect(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState;
socket.EndConnect(ar);
connectDone.Set();
}
private void EndSend(IAsyncResult ar)
{
Socket socket = (Socket)ar.AsyncState;
socket.EndSend(ar);
sendDone.Set();
}
private void EndReceive(IAsyncResult ar)
{
StateObject state = (StateObject)ar.AsyncState;
Socket socket = state.workSocket;
int length = socket.EndReceive(ar);
for (int j = 0; j < length; j++)
{
state.data.Add(state.buffer[j]);
}
if (!IsEnd(state.data.ToArray()))
{
socket.BeginReceive(state.buffer, 0, state.buffer.Length, SocketFlags.None, EndReceive, state);
}
else
{
if (state.data.Count > 0)
{
string receiveData = encode.GetString(state.data.ToArray(), 0, state.data.Count - endmark.Length);
//Console.WriteLine("Receive：" + receiveData);
OnSendCompleted(receiveData);
}
receiveDone.Set();
}
}
#endregion
#region private methods
private void DestroySocket(Socket socket)
{
if (socket != null)
{
if (socket.Connected)
{
socket.Shutdown(SocketShutdown.Both);
}
socket.Close();
}
}
private byte[] AddEndMark(string data)
{
byte[] databytes = encode.GetBytes(data);
byte[] result = new byte[databytes.Length + endmark.Length];
Array.Copy(databytes, 0, result, 0, databytes.Length);
Array.Copy(endmark, 0, result, databytes.Length, endmark.Length);
return result;
}
private bool IsEnd(byte[] data)
{
bool result = true;
if (data.Length >= endmark.Length)
{
for (int j = 0; j < endmark.Length; j++)
{
if (data[data.Length - 1 - j] != endmark[endmark.Length - 1 - j])
{
result = false;
break;
}
}
}
return result;
}
#endregion
}
}
重要说明：Receive的ReceiveTimeout对EndReceive不起作用，所以必须是双方约定一个结束符，或者发送方发送完毕立即关闭Socket来结束传输。
运行服务器监听数据：
复制内容到剪贴板 程序代码Server.Listen(8888);
发送和接收TCP数据：
复制内容到剪贴板 程序代码string data = "mzwu.com";
Client client = new Client();
client.SendCompleted += delegate(string message)
{
Console.WriteLine("Send：{0}\r\nReceive：{1}", data, message);
};
client.Send("127.0.0.1", 8888, data);
参考资料
[1].Socket 类：http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket(v=vs.80).aspx
[2].Socket 方法：http://msdn.microsoft.com/zh-cn/library/system.net.sockets.socket_methods(v=vs.80).aspx
[3].异步客户端套接字示例：http://msdn.microsoft.com/zh-cn/library/bew39x2a(v=vs.80).aspx
[4].异步服务器套接字示例：http://msdn.microsoft.com/zh-cn/library/fx6588te(v=vs.80).aspx

+ 查看当前日志评论 (0)

登录

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.336 ms

返回

标题: C#使用Socket发送和接收TCP数据示例(异步版)

你没有权限发表评论

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.336 ms

返回

暂无评论

返回

────────────

木子屋

PJBlog3 v3.2.9.518 Inside.

Processed In 1.383 ms

返回