服务端操作
//1、创建IPE
int port = 6000;
string host = "127.0.0.1";
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);
//2、创建socket
Socket sSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//3、绑定端口与ip
//如果要指定本地 IP 地址和端口号,请在调用 Listen 方法之前调用 Bind 方法
sSocket.Bind(ipe);
//4、监听,如果希望基础服务提供商为你分配一个可用端口,请使用端口号零
//如果使用面向连接的协议(例如 TCP),则服务器可以使用 Listen 方法侦听连接
sSocket.Listen(0);
Console.WriteLine("监听已经打开,请等待");
//5、获取通信socket
//receive message, Accept 方法处理任何传入连接请求,并返回可用于与远程主机通信的 Socket
Socket serverSocket = sSocket.Accept();
Console.WriteLine("连接已经建立");
string recStr = "";
byte[] recByte = new byte[4096];
//6、接收数据。若要传递数据,请调用 Send 或 Receive 方法
int bytes = serverSocket.Receive(recByte, recByte.Length, 0);
recStr += Encoding.ASCII.GetString(recByte, 0, bytes);
//send message
Console.WriteLine("服务器端获得信息:{0}", recStr);
string sendStr = "send to client :hello";
byte[] sendByte = Encoding.ASCII.GetBytes(sendStr);
//7、发送数据
serverSocket.Send(sendByte, sendByte.Length, 0);
serverSocket.Close();
sSocket.Close();
client
//1、创建ipe
int port = 6000;
string host = "127.0.0.1";//服务器端ip地址
IPAddress ip = IPAddress.Parse(host);
IPEndPoint ipe = new IPEndPoint(ip, port);
//2、创建socket
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//3、connect
clientSocket.Connect(ipe);
//4、send message
string sendStr = "send to server : hello,ni hao";
byte[] sendBytes = Encoding.ASCII.GetBytes(sendStr);
clientSocket.Send(sendBytes);
//5、receive message
string recStr = "";
byte[] recBytes = new byte[4096];
int bytes = clientSocket.Receive(recBytes, recBytes.Length, 0);
recStr += Encoding.ASCII.GetString(recBytes, 0, bytes);
Console.WriteLine(recStr);
clientSocket.Close();
下面的代码实现异步:
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Threading.Tasks;
// 客户端请求状态信息保存在这里
public class StateObject
{
// Client socket.
// 客户端的socket
public Socket workSocket = null;
// Size of receive buffer.
public const int BufferSize = 1024;
// Receive buffer.
public byte[] buffer = new byte[BufferSize];
// Received data string.
public StringBuilder sb = new StringBuilder();
}
public class AsynchronousSocketListener
{
public static List<Socket> ClientSockets = new List<Socket>();
// 线程信号
public static ManualResetEvent allDone = new ManualResetEvent(false);
/// <summary>
/// 构造函数
/// </summary>
public AsynchronousSocketListener()
{
}
/// <summary>
/// 开始监听
/// </summary>
public static void StartListening()
{
// Establish the local endpoint for the socket.
// The DNS name of the computer
// running the listener is "host.contoso.com".
IPHostEntry ipHostInfo = Dns.GetHostEntry(Dns.GetHostName());
IPAddress ipAddress = ipHostInfo.AddressList[3];
IPEndPoint localEndPoint = new IPEndPoint(ipAddress, 11000);
// Create a TCP/IP socket.
Socket listener = new Socket(ipAddress.AddressFamily,
SocketType.Stream, ProtocolType.Tcp);
// Bind the socket to the local endpoint and listen for incoming connections.
try
{
listener.Bind(localEndPoint);
listener.Listen(100);
Task.Run(()=> {
while (true)
{
// Set the event to nonsignaled state.
allDone.Reset();
// Start an asynchronous socket to listen for connections.
// AsyncCallback 让回调函数在单独的线程中执行
Console.WriteLine("Waiting for a connection...");
// 处理传入的请求,这个只有在客户端发起握手的时候才调用
listener.BeginAccept(
new AsyncCallback(AcceptCallback),
listener);
// Wait until a connection is made before continuing.
allDone.WaitOne();
}
});
while (true)
{
for (int i = 0; i < ClientSockets.Count; i++)
{
try
{
Send(ClientSockets[i], "hello i am server
");
}
catch (Exception)
{
ClientSockets.RemoveAt(i);
}
}
Thread.Sleep(100);
}
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
Console.WriteLine("
Press ENTER to continue...");
Console.Read();
}
/// <summary>
/// 监听回调
/// </summary>
/// <param name="ar"></param>
public static void AcceptCallback(IAsyncResult ar)
{
// 标记主线程继续执行
allDone.Set();
// 获取socket来处理client请求
Socket listener = (Socket)ar.AsyncState;
Socket handler = listener.EndAccept(ar);
// 创建数据对象(储存接收数据)
StateObject state = new StateObject();
state.workSocket = handler;
//存储请求来的socket,方便从server发送到client
ClientSockets.Add(handler);
Console.WriteLine(ClientSockets.Count);
// 处理传递进来的数据
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
/// <summary>
/// 读取客户端请求数据回调
/// </summary>
/// <param name="ar"></param>
public static void ReadCallback(IAsyncResult ar)
{
String content = String.Empty;
// Retrieve the state object and the handler socket
// from the asynchronous state object.
// 在read回调函数中调用 IAsyncResult(ar) 的 AsyncState 方法,以获取传递给 BeginReceive 方法的状态对象
// 此时就已经获取到客户端请求的数据,存储在state.buffer中,如果此时还有数据进来也不会填充state的buffer,而是等待下一次回调被调用
StateObject state = (StateObject)ar.AsyncState;
// 从此状态对象中提取接收 Socket
Socket handler = state.workSocket;
// Read data from the client socket.
// 获取 Client Socket后,可以调用 EndReceive 方法成功完成(关闭) BeginReceive 方法中启动的异步读取操作,并返回所读取的字节数
int bytesRead = handler.EndReceive(ar);
if (bytesRead > 0)
{
// There might be more data, so store the data received so far.
// 可能会有很多数据要接收,暂存当前已经接收到的数据,StateObject.buffer在ar.AsyncState的时候就已经被填充(实测)
state.sb.Clear();
state.sb.Append(Encoding.ASCII.GetString(state.buffer, 0, bytesRead));
// Check for end-of-file tag. If it is not there, read
// more data.
// 检查end-of-file,如果没哟检测到就再继续读。
content = state.sb.ToString();
Console.WriteLine(content);
/*
if (content.IndexOf("<EOF>") > -1)
{
// All the data has been read from the
// client. Display it on the console.
Console.WriteLine("Read {0} bytes from socket.
Data : {1}",
content.Length, content);
// Echo the data back to the client.
Send(handler, content);
}
else
{
// Not all data received. Get more.
// 没有读取到所有数据,继续读取,这里是个递归
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}*/
handler.BeginReceive(state.buffer, 0, StateObject.BufferSize, 0,
new AsyncCallback(ReadCallback), state);
}
}
private static void Send(Socket handler, String data)
{
// Convert the string data to byte data using ASCII encoding.
// 转换string到字节数组。使用ASCII编码
byte[] byteData = Encoding.ASCII.GetBytes(data);
// Begin sending the data to the remote device.
// 开始发送,异步发送
// 这里的handler是客户端client请求来的
handler.BeginSend(byteData, 0, byteData.Length, 0,
new AsyncCallback(SendCallback), handler);
}
/// <summary>
/// 发送回调,发送什么如何发送在这里实现
/// </summary>
/// <param name="ar"></param>
private static void SendCallback(IAsyncResult ar)
{
try
{
// Retrieve the socket from the state object
// 获取socket ,ar.AsyncState返回的是个object类型,可以转为state也可以转为socket
Socket handler = (Socket)ar.AsyncState;
// Complete sending the data to the remote device.
// 在回调方法中,调用 IAsyncResult 参数的 AsyncState 方法以获取发送 Socket。
// 获取 Socket后,可以调用 EndSend 方法成功完成发送操作,并返回发送的字节数。
int bytesSent = handler.EndSend(ar);
//Console.WriteLine("Sent {0} bytes to client.", bytesSent);
//handler.Shutdown(SocketShutdown.Both);
//handler.Close();
}
catch (Exception e)
{
Console.WriteLine(e.ToString());
}
}
public static int Main(String[] args)
{
StartListening();
return 0;
}
}