目录
引用: http://www.langsin.com
一、基础
◆广播数据
即从一个工作站发出,局域网内的其他所有工作站都能收到它。这一特征适用于无连接协议,因为
LAN上的所有机器都可获得并处理广播消息。使用广播消息的不利之处是每台机器都必须对该消息进行处理。比如,一用户在LAN上广播一条消息,每台机器上的网卡都会收到这条消息,并把它上
传到网络堆栈。然后,堆栈将这条消息在所有的网络应用中循环,看他们是否应该收到这条消息。通常,这个局域网上的多数机器对该消息都不感兴趣,草草地一弃了之。但是,各台机器仍需花时间来处理这个数据包,看是否有应用对它感兴趣。结果,高广播通信流使LAN上的机器陷入困境,因为每个工作站都要检查这个数据包。一般情况下,路由器都不会传送广播包。
◆多播数据
多播是指一个进程发送数据的能力,这些数据即将由一个或多个接收端进行接收。进程加入一个多播会话的方法和采用的基层协议有关。比如,IP协议下,多播是广播的一种变形,IP多播要求对收发数据感兴趣的所有主机加入一个特定的组。进程希望加入多播组时,网卡上会增添一个过滤器,这样,只有绑定组地址的数据才会被网络硬件捡起,并上传到网络堆栈进行恰当处理。视频会议应用常常使用多播。
传输控制协议、用户数据协议
1、socket
2、提供网络协议地址
//
3、从TCP网络客户端侦听连接
System.Net.Sockets.TcpListener:从TCP网络客户端侦听连接
4、为TCP网络服务提供客户端连接
5、将网络断点表示为IP地址和端口号
6、提供用于网络访问的基础数据流
7、实现Berkeley套接字接口
二、实例socket通信
1、socket通信程序
介绍:在阻塞模式下,两种服务端与两种客户端及逆行消息发送的演示
服务端:ConsoleServer
客户端:ConsoleClient
一、TCP
1、Server
创建Socket
绑定IP地址和端口号
监听 .Listen(100)
创建Socket clientSocket= serverSocket.Accept(
接收和发送:判断是否连接,,放到队列中
class Program
{
static void Main(string[] args)
{
// 1、Socket套接字
Socket tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); // 固定格式,地址族,数据流形式,协议类型
// 2、绑定ip和端口号
IPAddress ipaddress = new IPAddress(new byte[] {169,254,224,45 });
EndPoint point = new IPEndPoint(ipaddress,7788); // ipendpoint 是对ip+端口做了一层封装的类
tcpServer.Bind(point); // 想操作系统申请一个可用的ip和端口号,用来通信
tcpServer.Listen(100); // 监听
// 3、开始监听(等待客户端连接)
Socket clientSocket=tcpServer.Accept(); // 暂停当前线程,知道一个客户端连接过来,之后进行下面的代码
//
Console.WriteLine("一个客户端链接过来了");
// 使用返回的socket
string message = "hello world";
byte[] data=Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
//
byte[] data2 = new byte[1024]; // 创建一个字节数组用来当作容器,去承接客户端发送来的数据
int length = clientSocket.Receive(data2);
string messsage2 = Encoding.UTF8.GetString(data2, 0, length);
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace _003_聊天室_socket_tcp服务端
{
/*
* 1、服务端,客户端在unity 3D中
*
*
*
*
*/
class Program
{
static List<Client> clientList = new List<Client>();
static void Main(string[] args)
{
// 1创建 Socket,,服务端
Socket tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 2、绑IP和端口
IPAddress address = new IPAddress(new byte[] { 169, 254, 224, 45 });
EndPoint point = new IPEndPoint(address, 7788);
//public string ipaddress = "169, 254, 224, 45";
//public int port = 7788;
//clientSocket.Connect(new IPEndPoint(IPAddress.Parse(ipaddress), port));
tcpServer.Bind(point);
// 3、监听
tcpServer.Listen(100);
Console.WriteLine("server running...");
while (true)
{
Socket clientSocket = tcpServer.Accept();
Console.WriteLine("a client is comnected!");
Client client = new Client(clientSocket); // 把与每个客户端通信的逻辑(收发消息)放到client类里边进行处理
clientList.Add(client); // 把每次的客户端来的消息放到集合中
}
}
}
}
2、Client
创建Socket
连接IP地址和端口号
接收和发送
class Program
{
static void Main(string[] args)
{
// 1、创建客户端
Socket tcpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//IPAddress address = new IPAddress(new byte[] { 169, 254, 224, 45 });
//EndPoint point = new IPEndPoint(address,7788);
//tcpClient.Bind(point);
// 2、发起建立连接的请求
IPAddress address = new IPAddress(new byte[] { });
EndPoint point = new IPEndPoint(address, 7788);
tcpClient.Connect(point);
byte[] data = new byte[1024];
int length = tcpClient.Receive(data);
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine(message);
Console.ReadKey();
}
}
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace _003_聊天室_socket_tcp服务端
{
class UnityClient
{
public string ipaddress = "169, 254, 224, 45";
public int port = 7788;
private Socket clientSocket;
void ConnectToServer()
{
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 跟服务器简历连接
clientSocket.Connect(new IPEndPoint(IPAddress.Parse(ipaddress), port));
}
void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
}
}
3、TCP原理
4、TCPListener
class Program
{
static void Main(string[] args)
{
// 1、创建连接
TcpListener listener = new TcpListener(IPAddress.Parse("168.254.244.2"), 7788);
// 2、开始监听
listener.Start();
// 3、等待客户端连接过来
TcpClient client = listener.AcceptTcpClient(); // cpClient 封装好的方法
// 4、取得客户端发来的数据
NetworkStream stream = client.GetStream(); // 得到一个网络流,从这个网络流可以获得客户端发送过来的数据
byte[] data = new byte[1024];
// 5、循环接收消息
while (true)
{
int length = stream.Read(data, 0, 1024);
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine("收到了消息:" + message);
}
Console.ReadKey();
}
}
5、TCPclient
class Program
{
static void Main(string[] args)
{
// 当我们拆功能键tcpclient对象的时候,就会跟server去建立连接
TcpClient client = new TcpClient("168.254.244.2", 7788);
NetworkStream stream = client.GetStream(); // 通过网络流进行数据传递
while (true)
{
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
stream.Write(data, 0, data.Length);
}
stream.Close();
client.Close();
Console.ReadKey();
}
}
3、聊天室
1、Server
class Program
{
static List<Client> clientList = new List<Client>();
// 广播这个消息
public static void BroadcasrMessage(string message)
{
var notConnectedList = new List<Client>();
foreach (var client in clientList)
{
if (client.Connected) // 判断是否连接
{
client.SendMessage(message);
}
else
{
notConnectedList.Add(client);
}
}
// 移除未连接的连接
foreach(var temp in notConnectedList)
{
clientList.Remove(temp);
}
}
static void Main(string[] args)
{
// 1创建 Socket,,服务端
Socket tcpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 2、绑IP和端口
IPAddress address = new IPAddress(new byte[] { 169, 254, 224, 45 });
EndPoint point = new IPEndPoint(address, 7788);
//public string ipaddress = "169, 254, 224, 45";
//public int port = 7788;
//clientSocket.Connect(new IPEndPoint(IPAddress.Parse(ipaddress), port));
tcpServer.Bind(point);
// 3、监听
tcpServer.Listen(100);
Console.WriteLine("server running...");
while (true)
{
Socket clientSocket = tcpServer.Accept(); // 一直等待
Console.WriteLine("a client is comnected!");
Client client = new Client(clientSocket); // 把与每个客户端通信的逻辑(收发消息)放到client类里边进行处理
// clientSocket.Shu
// clientSocket.Close(); 关闭连接
clientList.Add(client); // 把每次的客户端来的消息放到集合中
}
}
}
class Client
{
private byte[] data = new byte[1024];
private Socket clientSocket;
public Client(Socket s) // 构造方法
{
clientSocket = s;
// 开启一个线程,处理客户端的数据接受
Thread t = new Thread(ReceiveMessage);
t.Start();
}
// 接收消息
private void ReceiveMessage()
{
// 接受消息,抑制接受客户端消息
while (true)
{
// 在接受之前判断是否断开
if(clientSocket.Poll(10, SelectMode.SelectRead)) // (clientSocket.Connected == false),, 判断是否断开连接,,true 为断开连接
{
//clientSocket.Poll(10, SelectMode.SelectRead);
break; // 跳出循环
}
int length=clientSocket.Receive(data);
string message = Encoding.UTF8.GetString(data);
// 接收到的消息,把这个数据发到客户端 ,
// 广播这个消息
Program.BroadcasrMessage(message);
Console.WriteLine("收到消息" + message);
}
}
/// <summary>
/// 发送消息
/// </summary>
/// <param name="message"></param>
public void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
// 判断是否连接
public bool Connected
{
get
{
return clientSocket.Connected;
}
}
}
2、TCP
class UnityClient
{
public string ipaddress = "169, 254, 224, 45";
public int port = 7788;
private Socket clientSocket;
private Thread t;
void ConnectToServer()
{
clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
// 跟服务器简历连接
clientSocket.Connect(new IPEndPoint(IPAddress.Parse(ipaddress), port));
// 创建一个新的线程,用来接受消息
t = new Thread(ReceiveMessage);
t.Start();
}
void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
void ReceiveMessage()
{
byte[] data = new byte[1024];
while (true)
{
if(clientSocket.Poll(10, SelectMode.SelectRead)) // 判断是否断开连接
{
break;
}
int length = clientSocket.Receive(data);
string message = Encoding.UTF8.GetString(data, 0, length); // 放到显示框里边
}
}
}
二、UDP
只需要建立Socket、
然后绑定IP地址端口号即可
然后客户端发送数据时候需要指定对应端口号和IP地址即可
发送接收都必须指定:对应端口号和IP地址即可
1、udpServer
class Program
{
static Socket udpServer;
static void Main(string[] args)
{
// 1、创建Socket
udpServer = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Udp);
// 2、绑定IP地址和端口号
udpServer.Bind(new IPEndPoint(IPAddress.Parse("168.254.224.6"), 7788));
// 3、接收数据,,没有简历连接的步骤
//EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
//byte[] data = new byte[1024];
//int length = udpServer.ReceiveFrom(data, ref remoteEndPoint); // 这个方法会把数据的来源(ip:port) 放到第二个参数上;
//string message = Encoding.UTF8.GetString(data, 0, length);
//Console.WriteLine("从ip:" + (remoteEndPoint as IPEndPoint).Address.ToString() + ":" + (remoteEndPoint as IPEndPoint).Port + "收到了数据");
new Thread(ReceiveMessage) { IsBackground = true }.Start();
//udpServer.Close();
Console.ReadKey();
}
static void ReceiveMessage()
{
while (true)
{
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
byte[] data = new byte[1024];
int length = udpServer.ReceiveFrom(data, ref remoteEndPoint); // 这个方法会把数据的来源(ip:port) 放到第二个参数上;
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine("从ip:" + (remoteEndPoint as IPEndPoint).Address.ToString() + ":" + (remoteEndPoint as IPEndPoint).Port + "收到了数据");
}
}
}
2、udpClient
class Program
{
static void Main(string[] args)
{
// 1、创建Socket
Socket udpClient = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Udp);
// 发送数据
while (true)
{
// 2、端口号
EndPoint point = new IPEndPoint(IPAddress.Parse("168.254.224.6"), 7788);
// 3、发送消息
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
udpClient.SendTo(data, point);
}
udpClient.Close();
Console.ReadKey();
}
}
3、UDP原理
占用资源少,不需要监听
4、udpServer
class Program
{
static void Main(string[] args)
{
// 1、创建连接
UdpClient udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse("168.254.224.2"), 7788));
while (true)
{
// 2、接收数据
IPEndPoint point = new IPEndPoint(IPAddress.Any, 0);
byte[] data = udpClient.Receive(ref point); // 通过point确定数据来自哪个IP的哪个端口号,返回是一个字节数组
string message = Encoding.UTF8.GetString(data);
Console.WriteLine(message);
}
Console.ReadKey();
}
}
5、udpclient -client
class Program
{
static void Main(string[] args)
{
UdpClient udpClient = new UdpClient();
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
udpClient.Send(data, data.Length, new IPEndPoint(IPAddress.Parse("168.254.224.2"), 7788));
udpClient.Close();
Console.ReadKey();
}