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);

     上面代码介绍了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

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

     服务器端所有代码:

  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 }

客户端实现

     客户端创建的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 }

测试结果:

 结语:

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

博客地址: http://www.cnblogs.com/wolf-sun/
博客版权: 本文以学习、研究和分享为主,欢迎转载,但必须在文章页面明显位置给出原文连接。
如果文中有不妥或者错误的地方还望高手的你指出,以免误人子弟。如果觉得本文对你有所帮助不如【推荐】一下!如果你有更好的建议,不如留言一起讨论,共同进步!
再次感谢您耐心的读完本篇文章。

转载:http://www.cnblogs.com/wolf-sun/p/3330221.html

时间: 2024-10-30 15:51:58

Socket网络编程(3)--两端通信的相关文章

Socket网络编程学习笔记(3):利用套接字助手类

在上一篇中已经介绍了利用Socket建立服务端和客户端进行通信,如果需要 的朋友可访问<Socket网络编程学习笔记(2):面向连接的Socket>.在本篇 中,将利用C#套接字的助手类来简化Socket编程,使得刚刚接触到网络编程的 朋友们更容易上手. 跟上篇一样,通过C#套接字的助手类来编程同样分 服务端和客户端. 一.服务端侦听模式 1.创建套接字与 IPEndPoint绑定,并设置为侦听模式. 1//创建IPEndPoint实例 2 IPEndPoint ipep = new IPEn

Python Socket 网络编程

原文:Python Socket 网络编程 Socket 是进程间通信的一种方式,它与其他进程间通信的一个主要不同是:它能实现不同主机间的进程间通信,我们网络上各种各样的服务大多都是基于 Socket 来完成通信的,例如我们每天浏览网页.QQ 聊天.收发 email 等等.要解决网络上两台主机之间的进程通信问题,首先要唯一标识该进程,在 TCP/IP 网络协议中,就是通过 (IP地址,协议,端口号) 三元组来标识进程的,解决了进程标识问题,就有了通信的基础了. 本文主要介绍使用 Python 进

python之Socket网络编程详解_python

什么是网络? 网络是由节点和连线构成,表示诸多对象及其相互联系.在数学上,网络是一种图,一般认为专指加权图.网络除了数学定义外,还有具体的物理含义,即网络是从某种相同类型的实际问题中抽象出来的模型.在计算机领域中,网络是信息传输.接收.共享的虚拟平台,通过它把各个点.面.体的信息联系到一起,从而实现这些资源的共享.网络是人类发展史来最重要的发明,提高了科技和人类社会的发展. 网络通信的三要素 IP地址 用来表示一台独立的主机 特殊的IP地址 127.0.0.1或称localhost(表示本地回环

【转】Windows Socket网络编程(二)----套接字编程原理

Windows Socket 网络编程(二) -- 套接字编程原理作者: 冰点工作室 小鹰 一.客户机/服务器模式在TCP/IP网络中两个进程间的相互作用的主机模式是客户机/服务器模式(Client/Server model).该模式的建立基于以下两点:1.非对等作用:2.通信完全是异步的.客户机/服务器模式在操作过程中采取的是主动请示方式: 首先服务器方要先启动,并根据请示提供相应服务:(过程如下)1.打开一通信通道并告知本地主机,它愿意在某一个公认地址上接收客户请求.2.等待客户请求到达该端

Socket网络编程学习笔记(1):常用方法介绍

虽然天天上博客园欣赏各位"大侠"的杰作,偶然回首,突然发 现自己已成"潜水者"久矣.本来对于自己有限的水平,有点不好意 思在此发贴,不过潜伏久了,才慢慢意识到老是通过浏览他人的文章虽然能够提 高自己能力,能够及时的获取新技术新思想,但却只能停留在他人的思想上.通 过学习,加上自己的想法,再写出来,让大家来指证错误,不仅能够巩固自己的 知识,也可以让一些跟我一样迷惘的朋友们不用再去走一些弯路,岂不是两全其 美,本着这样的想法,打算把自己平时的所学所想都写下来,欢迎各路

socket 网络编程传输文件

问题描述 socket 网络编程传输文件 进行网络通信,socket编程,传输文件过程中,如何来通过调用函数来获得传输文件的大小,以及传输该文件相对应的时间,有什么好的办法吗? 解决方案 从来没弄过Socket的一些东西,最近看了看,一些小东西,希望能帮到和我一样的菜鸟.1.win32程序下的文件传输1.1.Client Code#include #include long GetFileLen(FILE *_file){ long curPosit=ftell(_file)fileLen; f

socket网络编程 文件传输的问题?

问题描述 socket网络编程 文件传输的问题? socket网络编程,目前是同时开启两个进程两个线程,同时从server那端传输两个文件过来,是可以实现,任意格式的文件和任何大小的文件都可以.现在的项目要求是这两个进程要同时传输一个文件.我的思路是一个进程传输该文件的前一半,另一个进程传输该文件的后一半,具体实现就不知道了,希望大家给点意见,已经摸索了好几天.毫无头绪啊!!!!!项目马上就要完成了,谢谢大家. 解决方案 RandomAccessFile,看看吧. 解决方案二: 循序渐进Sock

socket-Windows Socket网络编程中使用的IP地址是公网IP还是内网IP?

问题描述 Windows Socket网络编程中使用的IP地址是公网IP还是内网IP? 因为我按照书上的代码写了一个程序,就是connect什么什么的,我写的MFC做客户端,网络调试助手做服务器端,然后从网络调试助手向MFC程序发送信息.当网络调试助手和MFC程序在一台电脑上时连接是可以成功的,但是在两台电脑上时就不成功了,调试的时候就是connect半天没反应,然后就失败了.IP地址我都填对的.(如果是两个网络调试助手在两台电脑上是能成功连接的,但是我找不到网络调试助手的源代码) 有谁知道是什

Socket 网络编程实践经验

目录 目录 相关文章 Socket 与 HTTP 的区别 生产实践考虑 网络断开重连问题 Heartbeat 心跳机制 使用非阻塞模式下的 select 函数进行 Socket 连接检查 会话过期问题 同步还是异步问题 数据缓存问题 完全断开连接问题 相关文章 NOTE:本文假设你已经对 Socket 的使用有一定的了解. Python Module_Socket_网络编程 Socket 与 HTTP 的区别 首先通过对比法来了解两者不同的特性: HTTP:超文本传输协议,首先它是一个协议,并且