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 }
View Code

客户端代码(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 }
View Code

异步模式(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 }
View Code

异步模式测试代码(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 }
View Code

百度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
View Code

 

参考文献:

http://www.cnblogs.com/gaobing/p/3860127.html

http://blog.csdn.net/hartkevin/article/details/5220536

http://www.csharpwin.com/csharpspace/13263r8436.shtml

posted @ 2014-08-07 09:40  壬子木  阅读(250)  评论(0)    收藏  举报