引言

项目中用到了Socket,这里做个控制台小示例记录一下。

Client

客户端的Receive用了异步方法,保持长连接,可以随时发送消息和响应服务端的消息,如下

        static string ClientReceiveMessage = "";
static byte[] receivedBytes = new byte[];
static void Main(string[] args)
{ IPHostEntry ipHost = Dns.Resolve("127.0.0.1");
IPAddress ipAddress = ipHost.AddressList[];
IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, ); string sendingMessage = "Hello World Socket Test"; Console.WriteLine("Creating message: Hello World Socket Test"); Socket sender = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
sender.Connect(ipEndPoint); sender.BeginReceive(receivedBytes, , receivedBytes.Length, , ReceiveCallback, sender); while (true)
{
sendingMessage = Console.ReadLine();
byte[] forwardMessage = Encoding.ASCII.GetBytes(sendingMessage + "[FINAL]");
sender.Send(forwardMessage);
}
} private static void ReceiveCallback(IAsyncResult ar)
{
Socket client = (Socket)ar.AsyncState; int totalBytesReceived = client.EndReceive(ar); if (totalBytesReceived > )
{ ClientReceiveMessage += Encoding.ASCII.GetString(receivedBytes, , totalBytesReceived);
if (ClientReceiveMessage.IndexOf("[FINAL]", StringComparison.Ordinal) > -)
{
Console.WriteLine(ClientReceiveMessage);
ClientReceiveMessage = "";
} client.BeginReceive(receivedBytes, , receivedBytes.Length, , new AsyncCallback(ReceiveCallback), client);
}
else
{
Console.WriteLine("服务端结束不再发送消息!" );
ClientReceiveMessage = "";
} }

Server

服务端循环异步Accept,可以接收多个client消息,并且马上回复。

        static ManualResetEvent allDone = new ManualResetEvent(false);
static void Main(string[] args)
{ Socket listener = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,
ProtocolType.Tcp);
listener.Bind(new IPEndPoint(IPAddress.Any, ));
listener.Listen(); while (true)
{
allDone.Reset();
listener.BeginAccept(ar =>
{
allDone.Set(); Socket MyServer = (Socket)ar.AsyncState; Socket service = MyServer.EndAccept(ar); byte[] receivedBytes = new byte[]; while (true)
{
string receivedValue = string.Empty;
int numBytes = service.Receive(receivedBytes);
receivedValue += Encoding.ASCII.GetString(receivedBytes,, numBytes); if (receivedValue.IndexOf("[FINAL]", StringComparison.Ordinal) > -)
{
Console.WriteLine("Received value: {0} from " + service.RemoteEndPoint, receivedValue);
string replyValue = "Message successfully received.[FINAL]";
byte[] replyMessage = Encoding.ASCII.GetBytes(replyValue);
service.Send(replyMessage);
}
}
}, listener); allDone.WaitOne();
}

注意事项

1.Socket的Receive方法响应次数,是以缓冲数组的大小划分。如果数组大小为1024,消息为2048,Receive将会触发两次。作为接收方无法通过Receive来确定是否已完整接收,所以要对消息另作处理,例如在消息中增加[FINAL]来确定消息已发送完毕。

2.如果没有消息发送,接收方Receive方法会一直等待。但如果发送方调用Shutdown(SocketShutdown.Send)方法,接收方的Receive会马上返回0,所以在非来回传递消息的情况下,可以Shutdown方法来实现消息发送完毕。

3.可以设置ReceiveTimeout的值,超时会抛出异常,然而只能作用于Receive方法,对BeginReceive无效。

05-11 16:14