关于Sokect的含义,还有Http等,可以看这篇文章Socket使用大全、Unity高级-Socket
TCP协议和UDP协议连接过程的区别:
服务器端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets; //添加命名空间
using System.Net; //添加命名空间
namespace _041_socket编程_tcp协议_服务器端
{
class Program
{
static void Main(string[] args)
{
//1.创建socket(socket本身就是一个类)
//AddressFamily.InterNetwork 内网(可省略),SocketType.Stream 通信方式,ProtocolType.Tcp 通信协议
Socket tcpServer = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,ProtocolType.Tcp);
//2.绑定ip跟端口号
//通过IP地址找到计算机,通过端口号找到软件(可以在cmd窗口中输入ipconfig获得)
//端口号0-60000,尽量取大点避免端口被占用
IPAddress ipaddress = new IPAddress(new byte[] {
192,168,0,102});//IP地址(因为IP是由4个255组成,所以使用new byte[])
EndPoint point = new IPEndPoint(ipaddress,7788); //ipendpoint是对ip+端口做了一层封装的类
//向操作系统申请一个可用的ip跟端口号用来做通信
tcpServer.Bind(point);
//3.开始监听(等待客户端连接)
tcpServer.Listen(100); //参数为最大连接数
Console.WriteLine("开始监听");
//暂停当前线程,接收客户端连接,之后进行下面的代码
Socket clientSocket = tcpServer.Accept();
Console.WriteLine("一个客户端连接成功");
//4.向客户端发送数据
//使用返回的socket跟客户端进行通信
string message = "已成功连接客户端";
byte[] data = Encoding.UTF8.GetBytes(message);//将字符串以UTF-8的编码格式转换为字节数组
clientSocket.Send(data); //向客户端发送消息
Console.WriteLine("向客户端发送数据");
///
///服务器端接收客户端发送回的数据
///
byte[] data2 = new byte[1024];
int length = clientSocket.Receive(data2);
string message2 = Encoding.UTF8.GetString(data2, 0, length);
Console.WriteLine("从客户端接收消息:" + message2);
Console.ReadKey();
}
}
}
客户端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace socket编程_tcp协议_客户端
{
class Program
{
static void Main(string[] args)
{
//1.创建socket
Socket tcpClient = new Socket(AddressFamily.InterNetwork,
SocketType.Stream,ProtocolType.Tcp);
//2.与服务器端连接(注意IP地址和端口要一致)
//可以把一个字符串的ip地址转化为ipadress的对象
IPAddress ipaddress = IPAddress.Parse("192.168.0.102");
//ip地址+端口号需与服务器端相同
EndPoint point = new IPEndPoint(ipaddress,7788);
//在客户端发起连接,通过ip和端口号定位一个要连接的服务器端
tcpClient.Connect(point);
//3.接收服务器端的数据
byte[] data = new byte[1024];
//data数组作为容器,用来接收数据,并返回一个表示接收了多少字节的长度
int length = tcpClient.Receive(data);
//从0开始,取length个字节的数据(不然会把所有数据转化)
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine(message);
///
/// 向服务器端发送消息
///
string message2 = Console.ReadLine();
tcpClient.Send(Encoding.UTF8.GetBytes(message2));
Console.ReadKey();
}
}
}
Client类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//添加下列命名空间
using System.Net.Sockets;
using System.Threading;
namespace _042_聊天室_socket_tcp服务器端
{
class Client
{
private Socket clientSocket;
private Thread t;
private byte[] data = new byte[1024];
public Client(Socket s)
{
clientSocket = s;
//启动一个线程,处理客户端的数据接收
t = new Thread(ReceiveMessage);
t.Start();
}
private void ReceiveMessage()
{
while (true) //一直接收客户端的数据
{
//在接收数据前,判断socket连接是否断开
//1.clientSocket.Connected == false
//2.另外一种方法判断是否连接(响应时间,判断是否能从客户端接收消息)
if (clientSocket.Poll(10, SelectMode.SelectRead))
{
clientSocket.Close();//关闭链接
break; //跳出一直接收数据的循环,终止线程执行
}
else
{
int length = clientSocket.Receive(data);
string message = Encoding.UTF8.GetString(data, 0, length);
//接收到数据的时候,要把这个数据分发到客户端(相当于广播消息)
//因为每个客户端都要看到这条消息嘛
Program.BroadcastMessage(message);
Console.WriteLine("接收到消息:" + message);
}
}
}
public void SendMessage(string message)
{
byte[] data = Encoding.UTF8.GetBytes(message);
clientSocket.Send(data);
}
public bool Connected //属性,是否断开连接
{
get{
return clientSocket.Connected; }
}
}
}
Program类:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//添加下列命名空间
using System.Net.Sockets;
using System.Net;
namespace _042_聊天室_socket_tcp服务器端
{
class Program
{
//1.创建socket,绑定ip和端口
static List<Client> clientList = new List<Client>();
static void Main(string[] args)
{
Socket tcpServer = new Socket(AddressFamily.InterNetwork,
SocketType.Stream, ProtocolType.Tcp);
tcpServer.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.104"), 7788));
//2.开始监听
tcpServer.Listen(100);
Console.WriteLine("server is running....");
//3.创建客户端对象
while (true) //使server能够一直接收到客户端的连接
{
Socket clientSocket = tcpServer.Accept();
Console.WriteLine("a client is connected!");
//把每个与客户端通信的逻辑放到client类里进行处理
Client client = new Client(clientSocket);
clientList.Add(client); //创建一个链表,添加连接的客户端
}
}
///
/// 广播消息
///
///
//服务器端接收到消息后对所有客户端进行广播
public static void BroadcastMessage(string message)
{
//保存已经断开的连接的客户端
var notConnectedList = new List<Client>();
foreach (var client in clientList)
{
if (client.Connected)//判断连接是否还在,才发送广播
{
client.SendMessage(message);
}
else//断开的话则保存到notConnectedList中
{
notConnectedList.Add(client);
}
}
foreach (var temp in notConnectedList)
{
clientList.Remove(temp);
}
}
}
}
using System.Collections;
using System.Collections.Generic;
using UnityEngine;
using System.Net.Sockets;
using System.Net;
using System.Text;
using UnityEngine.UI;
using System.Threading;
public class ChatManager : MonoBehaviour
{
private Socket clientSocket;
private Thread t;
private byte[] data = new byte[1024]; //数据容器
private string message = ""; //消息容器
public string ipaddress = "192.168.0.104"; //IP地址
public int port = 7788; //端口号
public UIInput textInput; //获取按钮组件
public UILabel chatLabel; //获取聊天窗口
// Start is called before the first frame update
void Start()
{
ConnectToServer();
}
// Update is called once per frame
void Update()
{
if (message!=null&&message!="") //消息显示在聊天窗口上
{
chatLabel.text += "\n"+message;
message = ""; //清空消息
}
}
//跟服务器端建立连接
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)
{
clientSocket.Send(Encoding.UTF8.GetBytes(message));
}
//事件-发送输入框的值
public void OnSendButtonClick()//UGUI按钮组件的On Click需要绑定这个事件
{
string value = textInput.value; //获取输入框的值
SendMessage(value);
textInput.text = ""; //发送完清空输入框
}
void OnDestroy() //OnDestroy是Unity的生命周期函数,跟Start()一样默认调用
{
clientSocket.Shutdown(SocketShutdown.Both);//关闭数据的发送和接收
clientSocket.Close(); //断开连接
}
///
/// 线程:用来循环接收消息
///
void ReceiveMessage()
{
while(true)
{
if (clientSocket.Connected == false)
{
break;
}
else
{
int length = clientSocket.Receive(data);
message = Encoding.UTF8.GetString(data, 0, length);
}
//unity不允许在单独的线程里操作Unity里的组件
//所以只能在Unity的生命周期函数里进行组件控制
//chatLabel.text += "\n" + message;
}
}
}
服务器端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Threading;
using System.Net.Sockets;
using System.Net;
namespace _043_socket编程_udp协议_服务器端
{
class Program
{
private static Socket udpServer;
static void Main(string[] args)
{
//1.创建socket
//SocketType.Dgrams以数据包形式发送
udpServer = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram,ProtocolType.Udp);
//2.绑定ip和端口号
//与tcp相比,udp少了监听这一步骤
udpServer.Bind(new IPEndPoint(IPAddress.Parse("192.168.0.104"), 7788));
//3.接收数据
//设置为后台线程,当程序关闭则结束线程
new Thread(ReceiveMessage) {
IsBackground=true}.Start();
//udpServer.Close(); //关闭连接
Console.ReadKey();
}
static void ReceiveMessage()
{
while(true) //udp不需要判断是否连接
{
byte[] data = new byte[1024];
//不需要指定具体的ip和端口号,因为是要用来赋值的
EndPoint remoteEndPoint = new IPEndPoint(IPAddress.Any, 0);
//ref能够改变传入参数的值,用来存放接收到的ip和端口号
//ReceiveFrom会暂停等待参数的传递,直到接收完才运行下面的代码
int length = udpServer.ReceiveFrom(data, ref remoteEndPoint);
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine("从ip:" + (remoteEndPoint as IPEndPoint).Address
+ ",端口号:" + (remoteEndPoint as IPEndPoint).Port
+ "接收到了数据:" + message);
}
}
}
}
客户端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace _002_socket编程_udp协议_客户端
{
class Program
{
static void Main(string[] args)
{
//1.创建socket
Socket udpClient = new Socket(AddressFamily.InterNetwork,
SocketType.Dgram,ProtocolType.Udp);
//2.发送数据(不需要连接)
while (true)
{
EndPoint serverPoint = new IPEndPoint(IPAddress.Parse("192.168.0.104"), 7788);
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
udpClient.SendTo(data, serverPoint);
}
Console.ReadKey();
}
}
}
应用程序可以通过TCPClient、TCPListener和UDPClient类使用 传输控制协议(TCP) 和 用户数据文报协议(UDP) 服务。这些协议类建立在System.Net.Sockets类的基础上,负责数据传送的细节。
(就是说TCPClient、TCPListener和UDPClient是用来简化socket的)
TCPClient和TCPListener使用NetworkStream类表示网格,使用GetStream方法返回网络流,然后调用该流的Read和Write方法。NetWorkStream不拥有协议类的基础套接字,因此关闭它并不影响套接字
UdpClient类使用字节数组保存UDP数据文报。使用Send方法向网络发送数据,使用Receive方法接收传入的数据文报
TcpClient类提供了一些简单的方法,用于在同步阻止模式下通过网络来连接、发送和接收流数据。为使TcpClient连接并交换数据,使用TCP ProtocolType创建的TcpListener或Socket必须监听是否有传入的连接请求。
可以使用下面两种方法之一连接到该侦听器:
给继承者说明要发送和接收数据,请使用GetStream方法来获取一个NetworkStream。调用NetworkStream的Write和Read方法与远程主机之间发送和接收数据,使用Close方法释放与TcpClient关联的所有资源
服务器端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace _044_tcplistener
{
class Program
{
static void Main(string[] args)
{
//1.TcpListener对socket进行了一层封装,这个类里面自己会去创建socket对象
TcpListener tcpListener = new TcpListener(IPAddress.Parse("192.168.0.104"),7788);
//2.开始监听
tcpListener.Start();
//3.等待客户端进行连接
TcpClient client = tcpListener.AcceptTcpClient();
//4.取得客户端发来的数据
//获得一个网络流,从这个网络流可以取得客户端发送过来的数据
NetworkStream stream = client.GetStream();
byte[] data = new byte[1024];//创建一个数据容器,用来装载数据
while (true)
{
//00表示从数组的第几个索引开始存放数据
//1024表示最大可读取的字节数
int length = stream.Read(data, 0, 1024);
string message = Encoding.UTF8.GetString(data, 0, length);
Console.WriteLine("获得的消息为:" + message);
}
//收到消息后,释放程序
stream.Close();
client.Close();
tcpListener.Stop(); //停止监听
Console.ReadKey();
}
}
}
客户端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace _003_tcpclient
{
class Program
{
static void Main(string[] args)
{
//1.当我们创建tcpclient对象的时候,会自动跟server建立连接
TcpClient client = new TcpClient("192.168.0.104",7788);
//2.通过网络流进行数据的交换
NetworkStream stream = client.GetStream();
//3.发送数据
while (true)
{
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
//read用来读取数据(接收数据),write用来写入数据(发送数据)
stream.Write(data, 0, data.Length);
}
stream.Close();
client.Close();
Console.ReadKey();
}
}
}
UdpClient类提供了一些简单的方法,用于在阻止同步模式下发送和接收无连接UDP数据报。因为UDP是无连接传输协议,所以不需要在发送和接收数据前建立远程主机连接。
可以选择使用下面两种方法之一来建立默认远程主机:
服务端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace _045_udpclient
{
class Program
{
static void Main(string[] args)
{
//1.创建udpclient,绑定ip和端口号
UdpClient udpClient = new UdpClient(new IPEndPoint(IPAddress.Parse("192.168.0.105"), 7788));
//2.创建一个IPEndPoint接收数据
IPEndPoint point = new IPEndPoint(IPAddress.Any,0);
while (true)
{
byte[] data = udpClient.Receive(ref point);
string message = Encoding.UTF8.GetString(data);
Console.WriteLine("收到了消息:" + message);
}
udpClient.Close();
Console.ReadKey();
}
}
}
客户端:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net.Sockets;
using System.Net;
namespace _004_udpclient
{
class Program
{
static void Main(string[] args)
{
//1.创建udpclient对象
UdpClient client = new UdpClient();
//2.发送数据
while (true)
{
string message = Console.ReadLine();
byte[] data = Encoding.UTF8.GetBytes(message);
client.Send(data, data.Length, new IPEndPoint(IPAddress.Parse("192.168.0.105"), 7788));
}
client.Close();
Console.ReadKey();
}
}
}