C#中Socket用法,多个聊天和单一聊天。

在C#中提供了两种网络服务,一种是Socket类,另一种是TcpListener(服务器),TcpClient(客户端);

至于这两种有什么区别那;MSDN上是这样解释的:

TcpClient 类, TcpListener 类 提供了一些简单的方法,用于在同步阻止模式下通过网络来连接、发送和接收流数据。

Socket 类为网络通信提供了一套丰富的方法和属性。 Socket 类允许您使用ProtocolType枚举中所列出的任何一种协议执行异步和同步数据传输。

 

先从第一个情景来说:第一个就是建立多人聊天的模式,就是多个客户端连接一个服务器,然后可以和多个客户端通信。就像QQ里的群聊。

首先我们来见一个服务器:

就包含一个文本框就行了,里边具体代码如下:

 1     public partial class server : Form
 2     {
 3         private IPEndPoint ServerInfo;//存放服务器的IP和端口信息
 4         private Socket ServerSocket;//服务端运行的SOCKET
 5         private Thread ServerThread;//服务端运行的线程
 6         private Socket[] ClientSocket;//为客户端建立的SOCKET连接
 7         private int ClientNumb;//存放客户端数量
 8         private byte[] MsgBuffer;//存放消息数据
 9 
10         private object obj;
11 
12         public server()
13         {
14             InitializeComponent();
15             ListenClient();
16         }
17 
18         /// <summary>
19         /// 开始服务,监听客户端
20         /// </summary>
21         private void ListenClient()
22         {
23             try
24             {
25                 ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
26                 IPAddress ip = IPAddress.Parse("127.0.0.1");
27                 ServerInfo = new IPEndPoint(ip, Int32.Parse("3000"));
28                 ServerSocket.Bind(ServerInfo);
29                 ServerSocket.Listen(10);
30 
31                 ClientSocket = new Socket[65535];
32                 MsgBuffer = new byte[65535];
33                 ClientNumb = 0;
34 
35                 ServerThread = new Thread(new ThreadStart(RecieveAccept));
36                 ServerThread.Start();
37             }
38             catch (System.Exception ex)
39             {
40 
41             }
42         }
43 
44         /// <summary>
45         /// 添加阻塞,监听客户端
46         /// </summary>
47         private void RecieveAccept()
48         {
49             while (true)
50             {
51                 //等待接受客户端连接,如果有就执行下边代码,没有就阻塞
52                 ClientSocket[ClientNumb] = ServerSocket.Accept();
53                 //接受客户端信息,没有阻塞,则会执行下边输出的代码;如果是Receive则不会执行下边输出代码
54                 ClientSocket[ClientNumb].BeginReceive(MsgBuffer, 0, MsgBuffer.Length, SocketFlags.None,
55                     new AsyncCallback(ReceiveCallback), ClientSocket[ClientNumb]);
56                 this.Invoke((MethodInvoker)delegate
57                 {
58                     lock (this.textBox1)
59                         this.textBox1.Text += "客户端:" + ClientNumb.ToString() + "连接成功!" + "\r\n";
60                 });
61                 ClientNumb++;
62             }
63         }
64 
65         /// <summary>
66         /// 回发数据到客户端
67         /// </summary>
68         /// <param name="ar"></param>
69         private void ReceiveCallback(IAsyncResult ar)
70         {
71             try
72             {
73                 Socket rSocket = (Socket)ar.AsyncState;
74                 int rEnd = rSocket.EndReceive(ar);
75 
76                 for (int i = 0; i < ClientNumb; i++)
77                 {
78                     if (ClientSocket[i].Connected)
79                     {
80                         //发送数据到客户端
81                         ClientSocket[i].Send(MsgBuffer, 0, rEnd, SocketFlags.None);
82                     }
83 
84                     //同时接受客户端回发的数据,用于回发
85                     rSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), rSocket);
86                 }
87             }
88             catch (System.Exception ex)
89             {
90 
91             }
92         }
93     }

然后我们添加客户端代码,客户端要一个按钮和两个文本框

具体代码如下:

 1     public partial class Client : Form
 2     {
 3         private IPEndPoint ServerInfo;
 4         private Socket ClientSocket;
 5         private object obj;
 6 
 7         //信息接收缓存
 8         private Byte[] MsgBuffer;
 9         //信息发送存储
10         private Byte[] MsgSend;
11 
12         public Client()
13         {
14             InitializeComponent();
15             ConnectServer();
16             this.button1.Click += new EventHandler(button1_Click);
17         }
18 
19         /// <summary>
20         /// 打开客户端,即连接服务器
21         /// </summary>
22         private void ConnectServer()
23         {
24             try
25             {
26                 ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
27                 MsgBuffer = new byte[65535];
28                 MsgSend = new byte[65535];
29                 IPAddress ip = IPAddress.Parse("127.0.0.1");
30                 ServerInfo = new IPEndPoint(ip, Int32.Parse("3000"));
31                 ClientSocket.Connect(ServerInfo);
32                 //发送信息至服务器
33                 ClientSocket.Send(Encoding.Unicode.GetBytes("用户: 进入系统!" + "\r\n"));
34                 ClientSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, SocketFlags.None,
35                     new AsyncCallback(ReceiveCallback), null);
36                 this.textBox1.Text += "登录服务器成功" + "\r\n";
37             }
38             catch (System.Exception ex)
39             {
40 
41             }
42         }
43 
44         /// <summary>
45         /// 回调时调用
46         /// </summary>
47         /// <param name="ar"></param>
48         private void ReceiveCallback(IAsyncResult ar)
49         {
50             int rEnd = ClientSocket.EndReceive(ar);
51             this.Invoke((MethodInvoker)delegate
52                  {
53                      lock (this.textBox1)
54                      {
55                          this.textBox1.Text += Encoding.Unicode.GetString(MsgBuffer, 0, rEnd) + "\r\n";
56                      }
57                  });
58             ClientSocket.BeginReceive(MsgBuffer, 0, MsgBuffer.Length, 0, new AsyncCallback(ReceiveCallback), null);
59         }
60 
61         /// <summary>
62         /// 发送信息
63         /// </summary>
64         /// <param name="sender"></param>
65         /// <param name="e"></param>
66         private void button1_Click(object sender, EventArgs e)
67         {
68             MsgSend = Encoding.Unicode.GetBytes("说:\n" + this.textBox2.Text + "\n\r");
69             if (ClientSocket.Connected)
70             {
71                 ClientSocket.Send(MsgSend);
72             }
73         }
74 
75     }
76 }

这样先运行服务器,在多运行几个客户端就可以了。

下边讲一下第二种案例:这种是多个客户端和服务器连接,每个客户端都可以和服务器通信,但是客户端之间没有通信,而且每个客户端和服务器通信时,不会影响其他客户端。

具体样式如图:

接着我们来看看具体的代码:

先来看看服务器的,样式和第一种一样,

具体代码:

 1     public partial class Server : Form
 2     {
 3         private Socket socket = null;
 4         private Thread thread = null;
 5 
 6         public Server()
 7         {
 8             InitializeComponent();
 9             StartListening();
10         }
11 
12         /// 
13         /// 开始监听客户端
14         /// 
15         private void StartListening()
16         {
17             try
18             {
19                 socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
20                 IPAddress ipaddress = IPAddress.Parse("127.0.0.1");
21                 IPEndPoint endPoint = new IPEndPoint(ipaddress, int.Parse("3000"));
22 
23                 socket.Bind(endPoint);
24                 socket.Listen(20);
25 
26                 thread = new Thread(new ThreadStart(WatchConnection));
27                 thread.IsBackground = true;
28                 thread.Start();
29 
30                 this.listBox1.Text = "开始监听客户端传来的消息" + "\r\n";
31             }
32             catch (System.Exception ex)
33             {
34                 this.listBox1.Text += "SocketException" + ex;
35             }
36         }
37 
38         Socket[] socConnection = new Socket[12];
39         private static int clientNum = 0;
40 
41         /// <summary>
42         /// 监听客户端发来的请求
43         /// </summary>
44         private void WatchConnection()
45         {
46             while (true)
47             {
48                 socConnection[clientNum] = socket.Accept();
49                 this.Invoke((MethodInvoker)delegate
50                 {
51                     this.listBox1.Text += "客户端连接成功" + "\r\n";
52                 });
53 
54                 Thread thread = new Thread(new ParameterizedThreadStart(ServerRecMsg));
55                 thread.IsBackground = true;
56                 thread.Start(socConnection[clientNum]);
57                 clientNum++;
58             }
59         }
60 
61         /// <summary>
62         /// 接受客户端消息并发送消息
63         /// </summary>
64         /// <param name="socketClientPara"></param>
65         private void ServerRecMsg(object socketClientPara)
66         {
67             Socket socketServer = socketClientPara as Socket;
68             try
69             {
70                 while (true)
71                 {
72                     byte[] arrServerRecMsg = new byte[1024 * 1024];
73                     int length = socketServer.Receive(arrServerRecMsg);
74 
75                     string strSRecMsg = Encoding.UTF8.GetString(arrServerRecMsg, 0, length);
76                     this.Invoke((MethodInvoker)delegate
77                     {
78                         this.listBox1.Text += "接收到:" + strSRecMsg + "\r\n";
79                     });
80 
81                     byte[] arrSendMsg = Encoding.UTF8.GetBytes("收到服务器发来的消息");
82                     //发送消息到客户端
83                     socketServer.Send(arrSendMsg);
84                 }
85             }
86             catch (System.Exception ex)
87             {
88 
89             }
90         }
91     }

再来看看客户端代码:

样式和第一种也一样:

 1     public partial class Client : Form
 2     {
 3         private Socket socketClient = null;
 4         private Thread threadClient = null;
 5 
 6         public Client()
 7         {
 8             InitializeComponent();
 9             ConnectionServer();
10             this.button1.Click += new EventHandler(button1_Click);
11         }
12 
13         /// <summary>
14         /// 连接服务器
15         /// </summary>
16         private void ConnectionServer()
17         {
18             socketClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
19             IPAddress ipaddress = IPAddress.Parse("127.0.0.1");
20             IPEndPoint endPoint = new IPEndPoint(ipaddress, int.Parse("3000"));
21             try
22             {
23                 socketClient.Connect(endPoint);
24                 threadClient = new Thread(RecMsg);
25                 threadClient.IsBackground = true;
26                 threadClient.Start();
27             }
28             catch (System.Exception ex)
29             {
30 
31             }
32 
33         }
34 
35         /// <summary>
36         /// 接收服务器消息
37         /// </summary>
38         private void RecMsg()
39         {
40             while (true)
41             {
42                 //内存缓冲区1M,用于临时存储接收到服务器端的消息
43                 byte[] arrRecMsg = new byte[1024 * 1024];
44                 //将接收到的数据放入内存缓冲区,获取其长度
45                 int length = socketClient.Receive(arrRecMsg);
46                 //将套接字获取到的字节数组转换为我们可以理解的字符串
47                 string strRecMsg = Encoding.UTF8.GetString(arrRecMsg, 0, length);
48                 this.Invoke((MethodInvoker)delegate
49                 {
50                     lock (this.listBox1)
51                     {
52                         this.listBox1.Text += "服务器:" + strRecMsg + "\r\n";
53                     }
54                 });
55             }
56         }
57 
58         /// <summary>
59         /// 向服务器发送消息
60         /// </summary>
61         /// <param name="sender"></param>
62         /// <param name="e"></param>
63         private void button1_Click(object sender, EventArgs e)
64         {
65             ClientSendMsg(this.textBox1.Text.Trim());
66         }
67 
68         /// <summary>
69         /// 发送信息到服务器
70         /// </summary>
71         /// <param name="sendMsg"></param>
72         private void ClientSendMsg(string sendMsg)
73         {
74             //将输入的字符串转化为机器可以识别的字节数组
75             byte[] arrClientSendMsg = Encoding.UTF8.GetBytes(sendMsg);
76             //发送数据
77             socketClient.Send(arrClientSendMsg);
78             this.listBox1.Text += "客户端:" + sendMsg + "\r\n";
79         }
80     }

到此两种方式就说完了,不知道说的对不对,请各位吐槽!!!,转载注明出处。

原文:http://www.cnphp6.com/archives/58259

posted @ 2017-01-09 13:20  DemiGoo  阅读(208)  评论(0编辑  收藏  举报