TCP Socket_C#

服务端代码(Server.cs):
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.Threading; 7 using System.Net; 8 9 namespace socket 10 { 11 class Server 12 { 13 // 通知一个或多个正在等待的线程已发生事件。 14 ManualResetEvent manager = new ManualResetEvent(false); 15 ManualResetEvent reviceManager = new ManualResetEvent(false); 16 17 // 负责监听的套接字 18 private Socket socketServer; 19 20 /// <summary> 21 /// 启动服务 22 /// </summary> 23 public void CreateSocketService() 24 { 25 try 26 { 27 // 获取IP 28 var address = IPAddress.Parse("127.0.0.1"); 29 // 创建一个包含ip port 的网络节点对象 30 Int32 Port = 12306; 31 var ipPoint = new IPEndPoint(address, Port); 32 // 创建一个套接字socket,参数(IP4寻址协议,流式连接,使用TCP协议传输数据) 33 socketServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 34 // 将负责监听的套接字绑定到唯一的IP和端口上 35 socketServer.Bind(ipPoint); 36 // 设置监听队列的长度,同时100个队列 37 socketServer.Listen(100); 38 // 线程开始监听客户端的请求 39 Thread threadService = new Thread(StartSocketService); 40 // 设置线程为后台线程 41 threadService.IsBackground = true; 42 // 启动线程 43 threadService.Start(); 44 // 显示消息 45 ShowMsg("服务器监听开启成功!"); 46 } 47 catch (Exception e) 48 { 49 ShowMsg(e.Message); 50 } 51 } 52 53 /// <summary> 54 /// 启动服务监听 55 /// </summary> 56 //private void StartSocketService() 57 public void StartSocketService() 58 { 59 while (true) 60 { 61 try 62 { 63 // 将事件状态设置为非终止状态,导致线程阻止 64 manager.Reset(); 65 // 开始监听客户端的连接请求 66 var args = new SocketAsyncEventArgs(); 67 args.Completed += args_Completed; 68 socketServer.AcceptAsync(args); 69 // 阻止当前线程,直到当前 WaitHandle 收到信号。 70 manager.WaitOne(); 71 } 72 catch (Exception ex) 73 { 74 ShowMsg(ex.Message); 75 break; 76 } 77 } 78 } 79 80 public void args_Completed(object sender, SocketAsyncEventArgs e) 81 { 82 // 监听完成客户端的请求,一但监听到返回新的套接字 83 var clientSocket = e.AcceptSocket; 84 // 启动线程获取客户端发来的消息 85 if (clientSocket == null) return; 86 // 这部分为接收消息 87 var t = new Thread(GetClientMsg); 88 // 设置线程为后台线程 89 t.IsBackground = true; 90 // 启动线程 91 t.Start(clientSocket); 92 // 显示信息 93 ShowMsg(clientSocket.RemoteEndPoint + "上线了"); 94 // 将事件状态设置为终止状态,允许一个或多个等待线程继续 95 manager.Set(); 96 } 97 98 void ShowMsg(string message) 99 { 100 // 显示消息 101 //txtConneMsg.AppendText("\r\n" + DateTime.Now + "\r\n\r\n" + message + "\r\n"); 102 Console.WriteLine("\r\n" + DateTime.Now + "\r\n\r\n" + message + "\r\n"); 103 } 104 105 private void GetClientMsg(object socket) 106 { 107 var socketClient = socket as Socket; 108 if (socketClient == null) return; 109 while (true) 110 { 111 try 112 { 113 reviceManager.Reset(); 114 var bytes = new byte[1024 * 1024 * 4]; 115 var receiveArgs = new SocketAsyncEventArgs(); 116 //设置缓冲区 117 receiveArgs.SetBuffer(bytes, 0, bytes.Length); 118 receiveArgs.Completed += receiveArgs_Completed; 119 //开始异步接收 120 socketClient.ReceiveAsync(receiveArgs); 121 reviceManager.WaitOne(); 122 } 123 catch (Exception ex) 124 { 125 //显示异常消息 126 ShowMsg(ex.Message); 127 } 128 } 129 } 130 131 void receiveArgs_Completed(object sender, SocketAsyncEventArgs e) 132 { 133 var socketClient = sender as Socket; 134 var bytes = e.Buffer; 135 ShowMsg(socketClient.RemoteEndPoint + "说:" + System.Text.Encoding.UTF8.GetString(bytes)); 136 reviceManager.Set(); 137 } 138 139 } 140 }
客户端代码(Client.cs):
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.Threading; 7 using System.Net; 8 9 namespace socket 10 { 11 class Client 12 { 13 private Socket socketClient; // 客户端套接字 14 private Thread threadClient; // 客户端线程 15 16 /// <summary> 17 /// 创建套接字连接到服务端 18 /// </summary> 19 //private void CreateSocketConnection() 20 public void CreateSocketConnection() 21 { 22 try 23 { 24 // 创建一个客户端的套接字 参数(IP4寻址协议,流连接方式,TCP数据传输协议) 25 socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); 26 // 获取IP 27 IPAddress address = IPAddress.Parse("127.0.0.1"); 28 //创建一个包含IP和端口号的网络节点对象 29 Int32 Port = 12306; 30 IPEndPoint ipPoint = new IPEndPoint(address, Port); 31 // 连接服务端 32 socketClient.Connect(ipPoint); 33 // 创建一个线程,接受服务端发来的数据 34 threadClient = new Thread(ReceiveService); 35 // 设置线程为后台线程 36 threadClient.IsBackground = true; 37 // 启动线程连接服务端 38 threadClient.Start(); 39 // 显示消息 40 ShowMsg("与服务器" + address.ToString() + ":" + Port.ToString() + "成功建立连接!"); 41 42 } 43 catch (Exception) 44 { 45 ShowMsg( "服务器未启动!"); 46 } 47 } 48 49 //private void ReceiveService() 50 public void ReceiveService() 51 { 52 while (true) 53 { 54 try 55 { 56 var b = new byte[1024 * 1024 * 4]; 57 int length = socketClient.Receive(b); 58 var msg = System.Text.Encoding.UTF8.GetString(b, 0, length); 59 ShowMsg(socketClient.RemoteEndPoint.ToString() + "对您: " + msg); 60 } 61 catch (Exception ex) 62 { 63 ShowMsg(ex.Message); 64 break; 65 } 66 } 67 } 68 69 public void ShowMsg(string msg) 70 { 71 //txtConneMsg.AppendText("\r\n" + DateTime.Now + "\r\n\r\n" + msg + "\r\n"); 72 Console.WriteLine("\r\n" + DateTime.Now + "\r\n\r\n" + msg + "\r\n"); 73 } 74 75 /// <summary> 76 /// 发送数据到服务端 77 /// </summary> 78 public void Send() 79 { 80 if (socketClient == null) 81 { 82 83 ShowMsg("服务器未启动!"); 84 return; 85 } 86 //byte[] b = System.Text.Encoding.UTF8.GetBytes(txtSend.Text.Trim()); 87 string txtSend = "Hello"; 88 byte[] b = System.Text.Encoding.UTF8.GetBytes(txtSend); 89 // 客户端向服务器发送消息 90 socketClient.Send(b); 91 //清空文本 92 ShowMsg("您对" + socketClient.RemoteEndPoint.ToString() + "说:" + txtSend); 93 txtSend = ""; 94 } 95 96 } 97 }
异步模式(SocketExtension.cs)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.Threading; 7 8 namespace SocketAsyncOpWithTimeOut 9 { 10 public static class SocketExtension 11 { 12 13 public static int EndReceive2(IAsyncResult ar) 14 { 15 var result = ar as AsyncResultWithTimeout; 16 result.AsyncWaitHandle.WaitOne(); 17 18 return result.ReceivedCount; 19 } 20 21 public static AsyncResultWithTimeout BeginReceive2 22 ( 23 this Socket socket, 24 int timeout, 25 byte[] buffer, 26 int offset, 27 int size, 28 SocketFlags flags, 29 AsyncCallback callback, 30 object state 31 ) 32 { 33 var result = new AsyncResultWithTimeout(callback, state); 34 35 var stateInfo = new StateInfo(result, socket); 36 37 socket.BeginReceive(buffer, offset, size, flags, ReceiveCb, state); 38 39 var registeredWaitHandle = 40 ThreadPool.RegisterWaitForSingleObject( 41 result.AsyncWaitHandle, 42 WatchTimeOut, 43 stateInfo, // 作为state传递给WatchTimeOut 44 timeout, 45 true); 46 47 // stateInfo中保存RegisteredWaitHandle,以方便在WatchTimeOut 48 // 中unregister. 49 stateInfo.RegisteredWaitHandle = registeredWaitHandle; 50 51 return result; 52 } 53 54 private static void WatchTimeOut(object state, bool timeout) 55 { 56 var stateInfo = state as StateInfo; 57 // 设置的timeout前,操作未完成,则设置为操作Timeout 58 if (timeout) 59 { 60 stateInfo.AsycResult.SetTimeout(); 61 } 62 63 // 取消之前注册的WaitOrTimerCallback 64 stateInfo.RegisteredWaitHandle.Unregister( 65 stateInfo.AsycResult.AsyncWaitHandle); 66 } 67 68 private static void ReceiveCb(IAsyncResult result) 69 { 70 var state = result.AsyncState as StateInfo; 71 var asyncResultWithTimeOut = state.AsycResult; 72 var count = state.Socket.EndReceive(result); 73 state.AsycResult.SetResult(count); 74 } 75 } 76 77 78 public class StateInfo 79 { 80 public StateInfo(AsyncResultWithTimeout result, Socket socket) 81 { 82 this.AsycResult = result; 83 this.Socket = socket; 84 } 85 86 public Socket Socket { get; private set; } 87 public AsyncResultWithTimeout AsycResult { get; private set; } 88 public RegisteredWaitHandle RegisteredWaitHandle { get; set; } 89 } 90 91 public class AsyncResultWithTimeout : IAsyncResult 92 { 93 private ManualResetEvent m_waitHandle = new ManualResetEvent(false); 94 public AsyncResultWithTimeout(AsyncCallback cb, object state) 95 { 96 this.AsyncState = state; 97 this.Callback = cb; 98 } 99 100 #region IAsyncResult 101 102 public object AsyncState { get; private set; } 103 public WaitHandle AsyncWaitHandle { get { return m_waitHandle; } } 104 public bool CompletedSynchronously { get { return false; } } 105 public bool IsCompleted { get; private set; } 106 107 #endregion 108 109 public AsyncCallback Callback { get; private set; } 110 public int ReceivedCount { get; private set; } 111 public bool TimedOut { get; private set; } 112 public void SetResult(int count) 113 { 114 this.IsCompleted = true; 115 this.ReceivedCount = count; 116 this.m_waitHandle.Set(); 117 118 if (Callback != null) Callback(this); 119 } 120 121 public void SetTimeout() 122 { 123 this.TimedOut = true; 124 this.IsCompleted = true; 125 this.m_waitHandle.Set(); 126 } 127 } 128 }
异步模式测试代码(Program.cs)
1 using System; 2 using System.Collections.Generic; 3 using System.Linq; 4 using System.Text; 5 using System.Net.Sockets; 6 using System.Threading; 7 8 namespace SocketAsyncOpWithTimeOut 9 { 10 public static class SocketExtension 11 { 12 13 public static int EndReceive2(IAsyncResult ar) 14 { 15 var result = ar as AsyncResultWithTimeout; 16 result.AsyncWaitHandle.WaitOne(); 17 18 return result.ReceivedCount; 19 } 20 21 public static AsyncResultWithTimeout BeginReceive2 22 ( 23 this Socket socket, 24 int timeout, 25 byte[] buffer, 26 int offset, 27 int size, 28 SocketFlags flags, 29 AsyncCallback callback, 30 object state 31 ) 32 { 33 var result = new AsyncResultWithTimeout(callback, state); 34 35 var stateInfo = new StateInfo(result, socket); 36 37 socket.BeginReceive(buffer, offset, size, flags, ReceiveCb, state); 38 39 var registeredWaitHandle = 40 ThreadPool.RegisterWaitForSingleObject( 41 result.AsyncWaitHandle, 42 WatchTimeOut, 43 stateInfo, // 作为state传递给WatchTimeOut 44 timeout, 45 true); 46 47 // stateInfo中保存RegisteredWaitHandle,以方便在WatchTimeOut 48 // 中unregister. 49 stateInfo.RegisteredWaitHandle = registeredWaitHandle; 50 51 return result; 52 } 53 54 private static void WatchTimeOut(object state, bool timeout) 55 { 56 var stateInfo = state as StateInfo; 57 // 设置的timeout前,操作未完成,则设置为操作Timeout 58 if (timeout) 59 { 60 stateInfo.AsycResult.SetTimeout(); 61 } 62 63 // 取消之前注册的WaitOrTimerCallback 64 stateInfo.RegisteredWaitHandle.Unregister( 65 stateInfo.AsycResult.AsyncWaitHandle); 66 } 67 68 private static void ReceiveCb(IAsyncResult result) 69 { 70 var state = result.AsyncState as StateInfo; 71 var asyncResultWithTimeOut = state.AsycResult; 72 var count = state.Socket.EndReceive(result); 73 state.AsycResult.SetResult(count); 74 } 75 } 76 77 78 public class StateInfo 79 { 80 public StateInfo(AsyncResultWithTimeout result, Socket socket) 81 { 82 this.AsycResult = result; 83 this.Socket = socket; 84 } 85 86 public Socket Socket { get; private set; } 87 public AsyncResultWithTimeout AsycResult { get; private set; } 88 public RegisteredWaitHandle RegisteredWaitHandle { get; set; } 89 } 90 91 public class AsyncResultWithTimeout : IAsyncResult 92 { 93 private ManualResetEvent m_waitHandle = new ManualResetEvent(false); 94 public AsyncResultWithTimeout(AsyncCallback cb, object state) 95 { 96 this.AsyncState = state; 97 this.Callback = cb; 98 } 99 100 #region IAsyncResult 101 102 public object AsyncState { get; private set; } 103 public WaitHandle AsyncWaitHandle { get { return m_waitHandle; } } 104 public bool CompletedSynchronously { get { return false; } } 105 public bool IsCompleted { get; private set; } 106 107 #endregion 108 109 public AsyncCallback Callback { get; private set; } 110 public int ReceivedCount { get; private set; } 111 public bool TimedOut { get; private set; } 112 public void SetResult(int count) 113 { 114 this.IsCompleted = true; 115 this.ReceivedCount = count; 116 this.m_waitHandle.Set(); 117 118 if (Callback != null) Callback(this); 119 } 120 121 public void SetTimeout() 122 { 123 this.TimedOut = true; 124 this.IsCompleted = true; 125 this.m_waitHandle.Set(); 126 } 127 } 128 }
百度Tcp包测试代码(TestSocketTcp.cs)
1 #region Test Socket.Tcp 2 3 private static void TestSocketTcp() 4 { 5 // 取得预保存的文件名 6 string fileName = "test.txt"; 7 // 远程主机 8 string hostName = "www.baidu.com"; 9 // 端口 10 int port = Int32.Parse("80"); 11 // 得到主机信息 12 IPHostEntry ipInfo = Dns.GetHostEntry(hostName); 13 // 取得 IPAddress[] 14 IPAddress[] ipAddr = ipInfo.AddressList; 15 // 得到ip 16 IPAddress ip = ipAddr[0]; 17 // 组合出远程终结点 18 IPEndPoint hostEP = new IPEndPoint(ip, port); 19 // 创建Socket 实例 20 Socket socket = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp); 21 try 22 { //尝试连接 23 socket.Connect(hostEP); 24 } 25 catch(Exception se) 26 { 27 Console.WriteLine("连接错误" + se.Message); 28 } 29 // 发送给远程主机的请求内容串 30 string sendStr = "GET / HTTP/1.1\r\nHost: " + hostName + "\r\nConnection: Close\r\n\r\n"; 31 // 创建bytes字节数组以转换发送串 32 byte[] bytesSendStr = new byte[1024]; 33 // 将发送内容字符串转换成字节byte数组 34 bytesSendStr = Encoding.ASCII.GetBytes(sendStr); 35 try 36 { // 向主机发送请求 37 socket.Send(bytesSendStr, bytesSendStr.Length, 0); 38 } 39 catch(Exception ce) 40 { 41 Console.WriteLine("发送错误:" + ce.Message); 42 } 43 // 声明接收返回内容的字符串 44 string recvStr = ""; 45 // 声明字节数组,一次接收数据的长度为1024字节 46 byte[] recvBytes = new byte[1024]; 47 // 返回实际接收内容的字节数 48 int bytes = 0; 49 // 循环读取,直到接收完所有数据 50 while(true) 51 { 52 bytes = socket.Receive(recvBytes, recvBytes.Length, 0); 53 // 读取完成后退出循环 54 if( bytes <= 0) break; 55 // 将读取的字节数转换为字符串 56 recvStr += Encoding.ASCII.GetString(recvBytes,0,bytes); 57 } 58 // 将所读取的字符串转换为字节数组 59 byte[] content = Encoding.ASCII.GetBytes(recvStr); 60 try 61 { 62 //创建文件流对象实例 63 FileStream fs = new FileStream(fileName, FileMode.OpenOrCreate, FileAccess.ReadWrite); 64 // 写入文件 65 fs.Write(content,0,content.Length); 66 } 67 catch(Exception fe) 68 { 69 Console.WriteLine("文件创建/写入错误:"+ fe.Message); 70 } 71 // 禁用Socket 72 socket.Shutdown(SocketShutdown.Both); 73 // 关闭Socket 74 socket.Close(); 75 } 76 #endregion
参考文献:
http://www.cnblogs.com/gaobing/p/3860127.html
http://blog.csdn.net/hartkevin/article/details/5220536
http://www.csharpwin.com/csharpspace/13263r8436.shtml

浙公网安备 33010602011771号