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

自己琢磨Socket刚刚几天,所以整理出来和大家共享一下。废话少说直接进入正题。

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

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

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

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

个人理解就是一个是用于简单的业务,一种用于复杂的业务。所以感觉是一样的。本文事例主要用Socket类来实现。一般来说复杂的会了,简单的应该也差不多了。

先从第一个情景来说:第一个就是建立多人聊天的模式,就是多个客户端连接一个服务器,然后可以和多个客户端通信。就像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     }

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

时间: 11-03

C#中Socket用法,多个聊天和单一聊天。的相关文章

java Socket用法详解(转)

在客户/服务器通信模式中, 客户端需要主动创建与服务器连接的 Socket(套接字), 服务器端收到了客户端的连接请求, 也会创建与客户连接的 Socket. Socket可看做是通信连接两端的收发器, 服务器与客户端都通过 Socket 来收发数据. 这篇文章首先介绍Socket类的各个构造方法, 以及成员方法的用法, 接着介绍 Socket的一些选项的作用, 这些选项可控制客户建立与服务器的连接, 以及接收和发送数据的行为. 一. 构造Socket Socket的构造方法有以下几种重载形式:

【转】JAVA网络编程之Socket用法

JAVA网络编程之Socket用法 分类: JAVA2012-08-24 15:56 710人阅读 评论(0) 收藏 举报 在客户/服务器通信模式中,客户端需要主动建立与服务器连接的Socket,服务器端收到客户端的连接请求,也会创建与客户端连接的Socket.Socket可以看做是通信连接两端的收发器,客户端和服务店都通过Socket来收发数据. 1.构造Socket public Socket() 通过系统默认类型的 SocketImpl 创建未连接套接字 public Socket(Str

Linux socket用法

转自:http://www.cnblogs.com/skynet/archive/2010/12/12/1903949.html  有删改 1.网络中进程之间如何通信? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用(Solaris门和Sun RPC) 但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一

typename在C++中的用法

1. //在C++中typename一般用来声明模板的模板参数(template parameter): template<typename T> class X; //T是一个模板参数 2. /*但是还有一个关键的用法.首先是两个概念: 1). qualified name 例如:std::cout, std::endl;这样含有作用域符号(::)的就是限定名, 当我们用using声明将cout,endl引入到当前作用域之后就可以直接使用 这两个名称,这个时候cout,endl就不是限定名了

C#中MessageBox用法大全(转)

我们在程序中经常会用到MessageBox. MessageBox.Show()共有21中重载方法.现将其常见用法总结如下: 1.MessageBox.Show("Hello~~~~"); 最简单的,只显示提示信息. 2.MessageBox.Show("There are something wrong!","ERROR"); 可以给消息框加上标题. 3.if (MessageBox.Show("Delete this user?&q

【转】 从最简单的vector中sort用法到自定义比较函数comp后对结构体排序的sort算法

sort函数在使用中非常好用,也非常简单,而且效率与冒泡或者选择排序不是一个数量级.本文就sort函数在vector中的用法分为sort函数入门用法与自定义comp比较函数比较结构体这两个最基本的功能讲讲其用法: 1.sort入门: 使用sort需要包含algorithm头文件,完整代码如下 #include<iostream> #include<vector> #include<algorithm>//貌似可以不用,但最好加上. using namespace std

[转载]C#中MessageBox.Show用法以及VB.NET中MsgBox用法

一.C#中MessageBox.Show用法 MessageBox.Show (String) 显示具有指定文本的消息框. 由 .NET Compact Framework 支持. MessageBox.Show (IWin32Window, String) 在指定对象的前面显示具有指定文本的消息框. MessageBox.Show (String, String) 显示具有指定文本和标题的消息框.由 .NET Compact Framework 支持. MessageBox.Show (IWi

IOS中NSdate用法

// date方法返回的就是当前时间(now) 02. NSDate *date = [NSDate date]; 03.// now: 11:12:40 04.// date: 11:12:50 05. date = [NSDate dateWithTimeIntervalSinceNow:10];//返回当前时间10秒后的时间 06. // 从1970-1-1 00:00:00开始 07. date = [NSDate dateWithTimeIntervalSince1970:10];//

IOS中NSSarry用法

一.创建数组 // 创建一个空的数组 02.NSArray *array = [NSArray array]; 03.// 创建有1个元素的数组 04.array = [NSArray arrayWithObject:@"123"]; 05.// 创建有多个元素的数组 06.array = [NSArray arrayWithObjects:@"a", @"b", @"c", nil nil]; 07.NSArray *arr