提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
网络通讯
- 前言
- 一、了解编写服务器demo
- 二、一之中的不足:只能接受一个客户端发送的消息,如何改进?
- 1.消息的广播
- 2.异步服务器
- 3.使用面向对象思想改进异步服务器
- 总结
前言
提示:这里可以添加本文要记录的大概内容:
例如:随着人工智能的不断发展,机器学习这门技术也越来越重要,很多人都开启了学习机器学习,本文就介绍了机器学习的基础内容。
提示:以下是本篇文章正文内容,下面案例可供参考
一、了解编写服务器demo
一、基础知识
Server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace Server1._0
{
class Program
{
static void Main(string[] args)
{
//Socket:套接字 :一个集合,IP地址和端口号、双方都需要同时满足的协议,地址族
//AddressFamily:地址族
// SocketType:传输类型,如果使用TCP协议的话,就选用Stream流式传输,如果使用UDP协议,就选择Dgram
// ProtocolType:协议类型
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//IP地址
IPAddress IP = IPAddress.Parse("192.168.1.96");
int port = 8888;//端口号,1-65535 ,一般1-1024系统端口,BSD保留端口 1024-5000临时端口,剩余的为用户自定义的端口
//重点掌握:使用服务器进行数据传输
serverSocket.Bind(new IPEndPoint(IP,port));
serverSocket.Listen(10);//参数表示同一时间内能处理的最大消息数
Console.WriteLine("服务器启动了");
//接受,接受一个客户端的连接
Socket clientSocket = serverSocket.Accept(); //阻塞函数
Console.WriteLine("服务器接受了一个客户端的连接,客户端的详细数据为:"+clientSocket.RemoteEndPoint.ToString());
byte[] msgArr = new byte[1024];
clientSocket.Receive(msgArr);
string msg = Encoding.UTF8.GetString(msgArr);
Console.WriteLine("从客户端接受到的数据为:"+msg);
Console.ReadKey();
}
}
}
Client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace Client1_0
{
class Program
{
static void Main(string[] args)
{
Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//客户端不需要绑定自己的IP地址和端口号
//而是去连接服务器的IP地址和端口号
IPAddress IP = IPAddress.Parse("192.168.1.96");
int port = 8888;
//Connect 连接,连接到一个终端()
clientSocket.Connect(new IPEndPoint(IP, port));
Console.WriteLine("连接到了服务器");
string connect = "666666"; //简体中文的编码格式:UTF-8,GB2312
byte[] msg = Encoding.UTF8.GetBytes(connect);
clientSocket.Send(msg);
Console.ReadLine();
}
}
}
二、一之中的不足:只能接受一个客户端发送的消息,如何改进?
利用多线程:
改进之后的server代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace Server1._0
{
class Program
{
static void Main(string[] args)
{
//Socket:套接字 :一个集合,IP地址和端口号、双方都需要同时满足的协议,地址族
//AddressFamily:地址族
// SocketType:传输类型,如果使用TCP协议的话,就选用Stream流式传输,如果使用UDP协议,就选择Dgram
// ProtocolType:协议类型
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//IP地址
IPAddress IP = IPAddress.Parse("192.168.1.96");
int port = 8888;//端口号,1-65535 ,一般1-1024系统端口,BSD保留端口 1024-5000临时端口,剩余的为用户自定义的端口
//重点掌握:使用服务器进行数据传输
serverSocket.Bind(new IPEndPoint(IP,port));
serverSocket.Listen(10);//参数表示同一时间内能处理的最大消息数
Console.WriteLine("服务器启动了");
Thread thread = new Thread(AcceptClient);
thread.Start(serverSocket);
Console.ReadKey();
}
//接受客户端发送的连接请求
private static void AcceptClient(object obj)
{
Socket serverSocket = obj as Socket;//父类转为子类
if(serverSocket == null)
{
return;
}
//Accept接受,接受一个客户端的连接
Socket clientSocket = serverSocket.Accept(); //阻塞函数
Console.WriteLine("服务器接受了一个客户端的连接,客户端的详细数据为:" + clientSocket.RemoteEndPoint.ToString());
//开启接受客户端发送消息的线程
Thread thread = new Thread(ReceiveMessage);
thread.Start(clientSocket);
//递归调用
AcceptClient(serverSocket);
}
//接受客户端发送的消息
private static void ReceiveMessage(object obj)
{
Socket clientSocket = obj as Socket;
if(clientSocket == null)
{
return;
}
byte[] msgArr = new byte[1024];
clientSocket.Receive(msgArr);
string msg = Encoding.UTF8.GetString(msgArr);
Console.WriteLine("从客户端接受到的数据为:" + msg);
ReceiveMessage(clientSocket);
}
}
}
1.消息的广播
server:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace Server1._0
{
class Program
{
//用来存放连接进来的客户端
static List<Socket> clientList = new List<Socket>();
static void Main(string[] args)
{
//Socket:套接字 :一个集合,IP地址和端口号、双方都需要同时满足的协议,地址族
//AddressFamily:地址族
// SocketType:传输类型,如果使用TCP协议的话,就选用Stream流式传输,如果使用UDP协议,就选择Dgram
// ProtocolType:协议类型
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//IP地址
IPAddress IP = IPAddress.Parse("192.168.1.96");
int port = 8888;//端口号,1-65535 ,一般1-1024系统端口,BSD保留端口 1024-5000临时端口,剩余的为用户自定义的端口
//重点掌握:使用服务器进行数据传输
serverSocket.Bind(new IPEndPoint(IP,port));
serverSocket.Listen(10);//参数表示同一时间内能处理的最大消息数
Console.WriteLine("服务器启动了");
Thread thread = new Thread(AcceptClient);
thread.Start(serverSocket);
Console.ReadKey();
}
//接受客户端发送的连接请求
private static void AcceptClient(object obj)
{
Socket serverSocket = obj as Socket;//父类转为子类
if(serverSocket == null)
{
return;
}
//Accept接受,接受一个客户端的连接
Socket clientSocket = serverSocket.Accept(); //阻塞函数
Console.WriteLine("服务器接受了一个客户端的连接,客户端的详细数据为:" + clientSocket.RemoteEndPoint.ToString());
clientList.Add(clientSocket);//加入List容器
//开启接受客户端发送消息的线程
Thread thread = new Thread(ReceiveMessage);
thread.Start(clientSocket);
//递归调用
AcceptClient(serverSocket);
}
//接受客户端发送的消息
private static void ReceiveMessage(object obj)
{
Socket clientSocket = obj as Socket;
if(clientSocket == null)
{
return;
}
byte[] msgArr = new byte[1024];
try
{
//Receive的返回值类型为int,返回的是这个数据的长度
int length = clientSocket.Receive(msgArr);
if(length == 0)
{
clientSocket.Close();
return;
}
string msg = Encoding.UTF8.GetString(msgArr, 0, length);
Console.WriteLine("从客户端接受到的数据为:" + msg);
byte[] messge = new byte[length];
Array.Copy(msgArr, 0, messge, 0, length);
for (int i = 0; i < clientList.Count; i++)
{
if(clientList[i] == clientSocket)
{
continue;
}
clientList[i].Send(messge);
}
}
catch (Exception e)
{
clientSocket.Close();
return;
}
ReceiveMessage(clientSocket);
}
}
}
client:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
using System.Threading;
namespace Client1_0
{
class Program
{
static Socket clientSocket;
static string name="我是朱思焱";
static void Main(string[] args)
{
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//客户端不需要绑定自己的IP地址和端口号
//而是去连接服务器的IP地址和端口号
IPAddress IP = IPAddress.Parse("192.168.1.96");
int port = 8888;
//Connect 连接,连接到一个终端()
clientSocket.Connect(new IPEndPoint(IP, port));
Console.WriteLine("连接到了服务器");
Thread thread = new Thread(ReceiveMessage);
thread.Start();
while (true)
{
string connect = name+":"+Console.ReadLine(); //简体中文的编码格式:UTF-8,GB2312
byte[] msg = Encoding.UTF8.GetBytes(connect);
clientSocket.Send(msg);
}
}
//消息的广播
/// <summary>
/// 客户端接受服务器发送的信息
/// </summary>
private static void ReceiveMessage()
{
//需要一个接受数据的数组
byte[] msgArr = new byte[1024];
//使用循环一直接受消息
while (true)
{
//需要知道信息的长度
int length = clientSocket.Receive(msgArr);
//解析消息
string msg = Encoding.UTF8.GetString(msgArr, 0, length);
//打印
Console.WriteLine("从服务器接收到的消息为:"+msg);
}
}
}
}
2.异步服务器
异步:Async,本质上仍然是一个多线程,异步连接必须
同步:程序由上而下的执行
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace AsyncChatSocket
{
class Program
{
//用于存放连接的客户端
static List<Socket> clientList = new List<Socket>();
static void Main(string[] args)
{
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//IP地址
IPAddress IP = IPAddress.Parse("192.168.1.96");
int port = 8888;//端口号,1-65535 ,一般1-1024系统端口,BSD保留端口 1024-5000临时端口,剩余的为用户自定义的端口
serverSocket.Bind(new IPEndPoint(IP, port));//重点掌握:使用服务器进行数据传输
serverSocket.Listen(10);//参数表示同一时间内能处理的最大消息数
Console.WriteLine("服务器启动了");
//异步的写法和开启新线程不一样
serverSocket.BeginAccept(AsyncAccept, serverSocket);
Console.ReadLine();
}
static byte[] msgArr = new byte[1024];
private static void AsyncAccept(IAsyncResult ar)
{
Socket serverSocket = ar.AsyncState as Socket;
if(serverSocket == null)
{
return;
}
//获取连接客户端
Socket clientSocket = serverSocket.EndAccept(ar);
clientList.Add(clientSocket);
Console.WriteLine(clientSocket.RemoteEndPoint.ToString());
//开启异步监听接受数据的方法
clientSocket.BeginReceive(msgArr, 0, msgArr.Length, SocketFlags.None, AsyncReceive,clientSocket);
serverSocket.BeginAccept(AsyncAccept, serverSocket);
}
private static void AsyncReceive(IAsyncResult ar)
{
Socket clientSocket = ar.AsyncState as Socket;
if (clientSocket == null)
{
return;
}
try
{
//Receive的返回值类型为int,返回的是这个数据的长度
int length = clientSocket.Receive(msgArr); //也是阻塞函数
if (length == 0)
{
clientSocket.Close();
clientList.Remove(clientSocket);
return;
}
string msg = Encoding.UTF8.GetString(msgArr, 0, length);
Console.WriteLine("从客户端接受到的数据为:" + msg);
byte[] messge = new byte[length];
Array.Copy(msgArr, 0, messge, 0, length);
for (int i = 0; i < clientList.Count; i++)
{
if (clientList[i] == clientSocket)
{
continue;
}
clientList[i].Send(messge);
}
}
catch (Exception e)
{
clientList.Remove(clientSocket);
return;
}
clientSocket.BeginReceive(msgArr, 0, msgArr.Length, SocketFlags.None, AsyncReceive, clientSocket);
}
}
}
3.使用面向对象思想改进异步服务器
客服代码:
using System.Text;
using System.Threading.Tasks;
namespace AsyncChatSocket
{
class ClientPeer
{
Socket ClientSocket = null;
byte[] msgArr = new byte[1024];
public ClientPeer(Socket clientSocket)
{
//初始化
this.ClientSocket = clientSocket;
clientSocket.BeginReceive(msgArr,0,msgArr.Length,SocketFlags.None,AsyncReceive,null);
}
//仅仅只做客户端消息的接受
private void AsyncReceive(IAsyncResult ar)
{
try
{
int length = ClientSocket.EndReceive(ar);
if(length == 0)
{
ClientSocket.Close();
return;
}
string msg = Encoding.UTF8.GetString(msgArr, 0, length);
Console.WriteLine(msg);
NetManager.Instance.BoardCastMessage(msg);
}
catch (Exception e)
{
ClientSocket.Close();
return;
}
ClientSocket.BeginReceive(msgArr, 0, msgArr.Length, SocketFlags.None, AsyncReceive, null);
}
//给自己管理的客户端发送消息
public void SendMessage(byte[] message)
{
ClientSocket.Send(message);
}
public void SendMessage(string message)
{
ClientSocket.Send(Encoding.UTF8.GetBytes(message));
}
}
}
客服管理者:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
namespace AsyncChatSocket
{
class NetManager
{
private static NetManager _instance = null;
private NetManager() { }
public static NetManager Instance
{
get
{
if(_instance == null)
{
_instance = new NetManager();
}
return _instance;
}
}
List<ClientPeer> clientList = new List<ClientPeer>();
public void AddClient(ClientPeer client)
{
clientList.Add(client);
}
public void RemoveClient(ClientPeer client)
{
clientList.Remove(client);
}
//广播消息
public void BoardCastMessage(string message,ClientPeer client=null)
{
for (int i = 0; i < clientList.Count; i++)
{
if (clientList[i] == client)
{
continue;
}
//通知客服给客户端发送消息
clientList[i].SendMessage(message);
}
}
public void BoardCastMessage(byte[] message, ClientPeer client = null)
{
for (int i = 0; i < clientList.Count; i++)
{
if (clientList[i] == client)
{
continue;
}
//通知客服给客户端发送消息
clientList[i].SendMessage(message);
}
}
//单独发送消息
public void SendMessage(byte[] message,ClientPeer client)
{
client.SendMessage(message);
}
public void SendMessage(string message, ClientPeer client)
{
client.SendMessage(message);
}
}
}
服务器代码:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace AsyncChatSocket
{
class Program
{
//用于存放连接的客户端
//static List<Socket> clientList = new List<Socket>();
static void Main(string[] args)
{
Socket serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//IP地址
IPAddress IP = IPAddress.Parse("192.168.1.96");
int port = 8888;//端口号,1-65535 ,一般1-1024系统端口,BSD保留端口 1024-5000临时端口,剩余的为用户自定义的端口
serverSocket.Bind(new IPEndPoint(IP, port));//重点掌握:使用服务器进行数据传输
serverSocket.Listen(10);//参数表示同一时间内能处理的最大消息数
Console.WriteLine("服务器启动了");
//异步的写法和开启新线程不一样
serverSocket.BeginAccept(AsyncAccept, serverSocket);
Console.ReadLine();
}
static byte[] msgArr = new byte[1024];
private static void AsyncAccept(IAsyncResult ar)
{
Socket serverSocket = ar.AsyncState as Socket;
if(serverSocket == null)
{
return;
}
//获取连接客户端
Socket clientSocket = serverSocket.EndAccept(ar);
//clientList.Add(clientSocket);
ClientPeer client = new ClientPeer(clientSocket);
NetManager.Instance.AddClient(client);
Console.WriteLine(clientSocket.RemoteEndPoint.ToString());
//开启异步监听接受数据的方法
//clientSocket.BeginReceive(msgArr, 0, msgArr.Length, SocketFlags.None, AsyncReceive,clientSocket);
serverSocket.BeginAccept(AsyncAccept, serverSocket);
}
//private static void AsyncReceive(IAsyncResult ar)
//{
// Socket clientSocket = ar.AsyncState as Socket;
// if (clientSocket == null)
// {
// return;
// }
// try
// {
// //Receive的返回值类型为int,返回的是这个数据的长度
// int length = clientSocket.Receive(msgArr); //也是阻塞函数
// if (length == 0)
// {
// clientSocket.Close();
// clientList.Remove(clientSocket);
// return;
// }
// string msg = Encoding.UTF8.GetString(msgArr, 0, length);
// Console.WriteLine("从客户端接受到的数据为:" + msg);
// byte[] messge = new byte[length];
// Array.Copy(msgArr, 0, messge, 0, length);
// for (int i = 0; i < clientList.Count; i++)
// {
// if (clientList[i] == clientSocket)
// {
// continue;
// }
// clientList[i].Send(messge);
// }
// }
// catch (Exception e)
// {
// clientList.Remove(clientSocket);
// return;
// }
// clientSocket.BeginReceive(msgArr, 0, msgArr.Length, SocketFlags.None, AsyncReceive, clientSocket);
//}
}
}
总结
提示:这里对文章进行总结:
例如:以上就是今天要讲的内容,本文仅仅简单介绍了pandas的使用,而pandas提供了大量能使我们快速便捷地处理数据的函数和方法。