Socket网络编程(3)--两端通信

     上篇博文:http://www.cnblogs.com/wolf-sun/p/3329558.html

     介绍了客户端连接服务端,一对一,多对一的情况,下面实现服务器接收消息的功能。LZ这些弄的比较慢,也是边学习,边动手实现的。具体步骤在注释中写的比较清楚,不懂的可以留言,LZ会尽快回复。共同学习,共同进步。

接收消息时机

      什么时候接收消息?当服务器开始监听,有客户端连接,并且连接成功,此时负责通信的Socket已经创建,此时就可以接收消息了,可以通过Socket的Receive()方法接收消息。

 1        // 摘要:

 2         //     从绑定的 System.Net.Sockets.Socket 套接字接收数据,将数据存入接收缓冲区。

 3         //

 4         // 参数:

 5         //   buffer:

 6         //     System.Byte 类型的数组,它是存储接收到的数据的位置。

 7         //

 8         // 返回结果:

 9         //     接收到的字节数。

10         //

11         // 异常:

12         //   System.ArgumentNullException:

13         //     buffer 为 null。

14         //

15         //   System.Net.Sockets.SocketException:

16         //     试图访问套接字时发生错误。 有关更多信息,请参见备注部分。

17         //

18         //   System.ObjectDisposedException:

19         //     System.Net.Sockets.Socket 已关闭。

20         //

21         //   System.Security.SecurityException:

22         //     调用堆栈中的调用方没有所需的权限。

23         public int Receive(byte[] buffer);
View Code

     上面代码介绍了Receive方法接收参数及返回值。

 1  private void ListenConn(object o)

 2         {

 3             //将参数o 转化为监听的socket

 4             Socket socketListener = o as Socket;

 5             //写入循环 每一个连接就创建一个通信用的socket

 6             while (true)

 7             {

 8                 //当有客户端连接成功 创建通信用的socket

 9                 Socket connSocket = socketListener.Accept();

10                 string ip = connSocket.RemoteEndPoint.ToString();

11                 ShowMsg(ip + " " + DateTime.Now.ToString() + " 连接成功");

12                //创建一个新线程去接收消息

13                 Thread th = new Thread(ReceiveMsg);

14                 th.Start(connSocket);

15 

16             }

17 
18 }

接收消息的代码:

 1   //接收客户端的消息

 2         private void ReceiveMsg(object o)

 3         {

 4             Socket connSocket = o as Socket;

 5 

 6             //通信用的socket连接成功 就可以接收消息了

 7             byte[] buffer = new byte[1024 * 1024 * 5];//5M缓存

 8             while (true)

 9             {

10                 //count是当前接收的字节个数

11                 int count = connSocket.Receive(buffer);

12                 string ip = connSocket.RemoteEndPoint.ToString();

13                 //判断接收到的字节个数 是0表示客户端关闭了

14                 if (count > 0)

15                 {

16 

17                     //将字节转换为字符串

18                     string msg = Encoding.UTF8.GetString(buffer, 0, count);

19                     ShowMsg(ip + " " + DateTime.Now.ToString() + "\r\n" + msg);

20                 }

21                 else

22                 {

23                     //socket没办法发送空消息 如果收到空消息 客户端关闭

24                     ShowMsg(ip + ":" + "断开连接");

25                     connSocket.Close();

26                     break;

27 

28                 }

29 

30             }

31 

32         }

测试:仍然用telnet命令来测试:telnet 127.0.0.1 50000
Socket网络编程(3)--两端通信

Socket网络编程(3)--两端通信

     测试结果:多对一,一对一,发送消息正常,关闭客户端,服务端正常显示哪个客户端断开连接。

     服务器端所有代码:

  1 using System;

  2 using System.Collections.Generic;

  3 using System.ComponentModel;

  4 using System.Data;

  5 using System.Drawing;

  6 using System.Linq;

  7 using System.Net;

  8 using System.Net.Sockets;

  9 using System.Text;

 10 using System.Threading;

 11 using System.Threading.Tasks;

 12 using System.Windows.Forms;

 13 

 14 namespace Wolfy.ChatServer

 15 {

 16     public partial class Server : Form

 17     {

 18         public Server()

 19         {

 20             InitializeComponent();

 21             //不让其检查跨线程的操作

 22             Control.CheckForIllegalCrossThreadCalls = false;

 23         }

 24         //存放endpoin和通信用的socket

 25         Dictionary<string, Socket> dic = new Dictionary<string, Socket>();

 26         private void btnSend_Click(object sender, EventArgs e)

 27         {

 28             ServerSendMsg(this.txtInputMsg.Text);

 29         }

 30         /// <summary>

 31         /// 服务器给客户端发送消息

 32         /// </summary>

 33         private void ServerSendMsg(string msg)

 34         {

 35             //服务器给客户端发消息

 36             string userkey = comboBoxEndpoint.Text;

 37             if (!string.IsNullOrEmpty(userkey))

 38             {

 39                 ShowMsg(msg);

 40                 byte[] buffer = Encoding.UTF8.GetBytes(msg);

 41                 dic[userkey].Send(buffer);

 42                 msg = "";

 43             }

 44             else

 45             {

 46                 MessageBox.Show("请选择客户端");

 47             }

 48         }

 49 

 50         private void btnStartService_Click(object sender, EventArgs e)

 51         {

 52             //服务器ip地址

 53             IPAddress ip = IPAddress.Parse(txtIPAddress.Text);

 54             //ip地址和端口

 55             IPEndPoint endpoint = new IPEndPoint(ip, int.Parse(txtPort.Text));

 56             //创建用于监听的socket

 57             Socket socketListener = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

 58             //绑定ip和端口

 59             socketListener.Bind(endpoint);

 60             //开始监听 限制连接数 最多可以连接10个

 61             socketListener.Listen(10);

 62             ShowMsg("开始监听......");

 63             //创建线程 去监听连接

 64             Thread th = new Thread(ListenConn);

 65             //将线程变为后台线程

 66             th.IsBackground = true;

 67             th.Start(socketListener);

 68         }

 69         private void ListenConn(object o)

 70         {

 71             //将参数o 转化为监听的socket

 72             Socket socketListener = o as Socket;

 73             //写入循环 每一个连接就创建一个通信用的socket

 74             while (true)

 75             {

 76                 //当有客户端连接成功 创建通信用的socket

 77                 Socket connSocket = socketListener.Accept();

 78                 string ip = connSocket.RemoteEndPoint.ToString();

 79                 ShowMsg(ip + " " + DateTime.Now.ToString() + " 连接成功");

 80                 //连接成功后加入字典

 81                 dic.Add(ip, connSocket);

 82                 comboBoxEndpoint.Items.Add(ip);

 83                 //创建一个新线程去接收消息

 84                 Thread th = new Thread(ReceiveMsg);

 85                 th.Start(connSocket);

 86             }

 87 

 88         }

 89         //接收客户端的消息

 90         private void ReceiveMsg(object o)

 91         {

 92             Socket connSocket = o as Socket;

 93 

 94             //通信用的socket连接成功 就可以接收消息了

 95             byte[] buffer = new byte[1024 * 1024 * 5];//5M缓存

 96             while (true)

 97             {

 98                 //count是当前接收的字节个数

 99                 int count = connSocket.Receive(buffer);

100                 string ip = connSocket.RemoteEndPoint.ToString();

101                 //判断接收到的字节个数 是0表示客户端关闭了

102                 if (count > 0)

103                 {

104                     //将字节转换为字符串

105                     string msg = Encoding.UTF8.GetString(buffer, 0, count);

106                     ShowMsg(ip + " " + DateTime.Now.ToString() + "\r\n" + msg);

107                 }

108                 else

109                 {

110                     //socket没办法发送空消息 如果收到空消息 客户端关闭

111                     ShowMsg(ip + ":" + "断开连接");

112                     connSocket.Close();

113                     break;

114                 }

115 

116             }

117 

118         }

119         /// <summary>

120         /// 提示信息辅助方法

121         /// </summary>

122         /// <param name="msg"></param>

123         private void ShowMsg(string msg)

124         {

125             this.txtMsgView.AppendText(msg + "\r\n");

126         }

127 

128         private void txtInputMsg_KeyUp(object sender, KeyEventArgs e)

129         {

130             //如果用户按下了Enter键

131             if (e.KeyCode == Keys.Enter)

132             {

133                 //则调用 服务器向客户端发送信息的方法

134                 ServerSendMsg(this.txtInputMsg.Text);

135             }

136         }

137     }

138 }
View Code

客户端实现

     客户端创建的socket即负责连接又负责通信,所以这里和服务端不同。客户端连接、接收消息和发送消息代码如下:

 1 using System;

 2 using System.Collections.Generic;

 3 using System.ComponentModel;

 4 using System.Data;

 5 using System.Drawing;

 6 using System.Linq;

 7 using System.Text;

 8 using System.Threading.Tasks;

 9 using System.Windows.Forms;

10 using System.Net.Sockets;

11 using System.Net;

12 using System.Threading;

13 namespace Wolf.ChatClient

14 {

15     public partial class Client : Form

16     {

17         public Client()

18         {

19             InitializeComponent();

20             //不让检查跨线程操作

21             Control.CheckForIllegalCrossThreadCalls = false;

22         }

23         Socket socket;

24         private void btnStartService_Click(object sender, EventArgs e)

25         {

26             //连接服务器的ip和端口

27             IPAddress ip = IPAddress.Parse(txtIPAddress.Text);

28             IPEndPoint endpoint = new IPEndPoint(ip, int.Parse(txtPort.Text));

29             //客户端的socket即负责连接又负责通信

30             socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

31             //连接服务器

32             socket.Connect(endpoint);

33             ShowMsg("连接成功......");

34             //和服务器连接成功后就可以接收服务端的消息了

35             Thread th = new Thread(ReceiveMsg);

36             th.IsBackground = true;

37             th.Start();

38 

39         }

40         private void ReceiveMsg()

41         {

42             byte[] buffer = new byte[1024 * 1024 * 5];

43             while (true)

44             {

45                 int count = socket.Receive(buffer);

46                 string msg = Encoding.UTF8.GetString(buffer, 0, count);

47                 ShowMsg(this.txtIPAddress.Text + ":" + this.txtPort.Text + "  " + DateTime.Now.ToString() + "\r\n" + msg);

48             }

49         }

50         private void ShowMsg(string msg)

51         {

52             txtMsgView.AppendText(msg + "\r\n");

53         }

54         private void btnSend_Click(object sender, EventArgs e)

55         {

56             ClientSendMsg(this.txtInputMsg.Text);

57         }

58 

59         /// <summary>

60         /// 客户端向服务端发送消息

61         /// </summary>

62         /// <param name="msg"></param>

63         private void ClientSendMsg(string msg)

64         {

65             //向服务端发送消息

66             if (socket != null)

67             {

68                 ShowMsg(msg);

69                 byte[] buffer = Encoding.UTF8.GetBytes(msg);

70                 socket.Send(buffer);

71                 msg = "";

72             }

73             else

74             {

75                 ShowMsg("<<<<请先连接服务器>>>");

76             }

77         }

78 

79         private void txtInputMsg_KeyUp(object sender, KeyEventArgs e)

80         {

81             //如果用户按下了Enter键

82             if (e.KeyCode == Keys.Enter)

83             {

84                 //则调用 服务器向客户端发送信息的方法

85                 ClientSendMsg(this.txtInputMsg.Text);

86             }

87         }

88 

89         private void Client_FormClosing(object sender, FormClosingEventArgs e)

90         {

91             //客户端关闭 关闭socket

92             socket.Shutdown(SocketShutdown.Both);

93         }

94     }

95 }
View Code

测试结果:
Socket网络编程(3)--两端通信


 结语:

       边学习,边动手,实现了两端通信,目前支持一对一,多对一通信功能,代码中针对关闭客户端的情况还有bug,有待进一步修改。

你可能感兴趣的:(socket)