一、Socket编程
1)在网络中计算机之间如何互相找到?什么是IP地址与端口?
TCP/IP(传输控制协议/网际协议)是一组网络通信协议的总成,它规范了网络上的所有通信设备,尤其是一个主机与另一个主机之间的数据交换格式以及传送方式。
IP(Internet Protocol)是Internet网络设备之间传输数据的一种协议,IP地址就是给每个连接在因特网上的主机(或路由器)分配一个在全世界范围内唯一的标识符。
端口(Port)标识某台计算机上的进程
2)TCP(传输控制协议)是TCP/IP体系中面向连接的运输层协议,在网络中提供全双工的和可靠的服务,TCP协议最主要的特点是:
1.是一种基于连接的协议。
2.保证数据准确到达。
3.保证个数据到达的顺序与数据发出的顺序相同。
3)UDP是一个简单的、面向数据的无连接协议,提供了快速但不一定可靠的传输服务。UDP协议最主要的特点是:
1.是基于无连接的协议,没有生成连接的系统延迟,所以速度必TCP更快。
2.支持一对一连接,也支持一对多连接,可以使用广播的方式多地址发送。
3.与TCP的报头比是8:20,这使得UDP消耗的网络宽带更少。
4.协议传输的数据有消息边界,而TCP协议没有消息边界。
4)套接字(Socket)
套接字是支持TCP/IP协议的网络通信的基本操作单元。可以将套接字看作不同主机间的进程进行双向通信的端点,它构成了单个主机内及整个网络间的编程界面。
5)Socket类的构造实例
Socket localSocket=new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
SocketType | ProtocolType | 说明 |
---|---|---|
Dgram | Udp | 无连接通信 |
Stream | Tcp | 面向连接的通信 |
Raw | Icmp | Internet控制报文协议 |
Raw | Raw | 简单IP包协议 |
二、面向连接的Socket
1)面向连接的(即:流式):安全但是效率低。在发送数据前,会先经历TCP的三次握手,建立连接,发送完毕会发生回执。全过程会一直保持连接状态,比较消耗资源。
2)面向连接的套接字中,使用TCP协议来建立两个IP地址端点之间的绘画。一旦建立了这种连接,就可以在设备之间可靠的传输数据。为了建立面向连接的套接字,服务器和客户端必须分别进行编程。、
3)面向连接通信步骤
服务器端:1.申请一个Socket 2.绑定到一个IP地址和端口上 3.开启监听,等待接收连接
客户端:1.申请体格Socket 2.连接服务器,且制定IP和端口号
特别注意:服务器端接到连接请求后,产生一个新的Socket(端口大于1024)与客户端建立连接并进行通讯,原来的监听Socket,继续监听
//学习Socket通讯技术
//服务器端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//需要引入的命名空间
using System.Net.Socket; //Socket命名空间
using System.Net; //网络命名空间
using System.Threading; //多线程命名空间
public class Server{
private Socket _SocketServer; //服务器监听Socket
private bool _IsListenContecion; //是否在监听(目的是方便退出)
public Server(){
//定义网络终结点(封装IP与端口),127.0.0.1表示本机,端口尽量大于1024
IPEndPoint endPoint=new IPEndPoint(IPAddress.Parse("127.0.0.1"),1050);
//实例化Socket(监听)
_SocketServer=new Socket(AddressFamily.InterNetWork,SocketType.Stream,ProtocolType.Tcp);
//服务器端绑定地址
_SocketServer.Bind(endPoint);
//开始监听
_SocketServer.Listen(10);//10表示监听队列的最大长度,可以改变
Console.WriteLine("服务器端已经启动");
try{
while(_IsListenContecion){
//Accept()方法,接收客户端的连接
//这个方法会阻断当前线程的运行,所以需要建立一个单独的线程
Socket sockMsgServer= _SocketServer.Accept();
Console.WriteLine("此时有一个客户端连接。。。");
//开启后台线程,进行客户端的会话
Thread thClientMsg=new Thread(ClientMsg);
thClientMsg.InBackground=true; //定义成后台线程
thClientMsg.Name="thClientMsg";
thClientMsg.Start(sockMsgServer);
}
}catch(Exception){
}
}
//服务器端与客户端的通信后台线程
//sockMsg表示服务器端的会话Socket
private void ClientMsg(objetc sockMsg){
Socket socketMsg=sockMsg as Socket; //通讯Socket
while(true){
//准备一个“数据缓存”
byte[] msgArray=new byte[1024*1024]; //最大长度1M空间
//接收客户端发来的数据,返回数据真实的长度
int trueClineMsgLength=socketMsg.Receive(msgArray);
//byte数组转String
String strMsg=Encoding.UTF8.GetString(msgArray,0,trueClineMsgLength);
//显示客户端发来的数据
Console.WriteLine("客户端发来的数据"+strMsg);
}
}
static void Main(string[] args){
Server obj=new Server();
}
}
//客户端,注意:应当新开个项目
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//需要引入的命名空间
using System.Net.Socket; //Socket命名空间
using System.Net; //网络命名空间
using System.Threading; //多线程命名空间
public class Client{
private Socket _SocketClient; //通讯Socket
private IPEndPoint sertEndPoint; //需要连接的服务器IP与端口信息
public Client(){
//(服务器端)通讯地址与端口号
sertEndPoint=new IPEndPoint(IPAddress.Parse("127.0.0.1"),1050);
//建立客户端的Socket
_SocketClient=new Socket(AddressFamily.InterNetWork,SocketType.Stream,ProtocolType.Tcp);
try{
_SocketClient.Connect();
}catch(Exception){
}
Console.WriteLine("连接服务器成功");
}
//连接服务器
public void SendMsg(){
while(true){
//输入信息
string strMsg=Console.ReadLine();
//退出
if(strMSg=="exit"){
break;
}
//字节转换
Byte[] byteArray=Encoding.UTF8.GetBytes(strMsg);
//发送数据
_SocketClient.Send(byteArray);
Console.WriteLine("我"+strMsg);
}
//关闭连接
_SocketClient.Shutdown(SocketShutdown.Both);
//清理连接资源
_SocketClient、Close();
}
static void Main(string[] args){
Client obj=new Client();
obj.SendMsg();
}
}
三、无连接的Socket、
1)无连接的(即:数据报文格式):UDP服务,不安全,但效率高。将数据拆成很多分(包),然后发给对方,对方是否收到不予以理睬。采取发生完毕就立即关闭连接的方式,比较省资源。例如:迅雷下载等。(可以“多点”
同时下载)
2)UDP协议使用无连接的Socket,无连接的套接字不需要在网络设备之间发送信息。须用Bind方法绑定到一个本地地址/端口对上。完成绑定之后,该设备就可以利用Scoket接收数据了。由于发送设备没有建立到接收设备地址的连接,所以收发数据均不需要Listen(),Connect()方法。
3)无连接Socket通讯步骤
建立一个Socket
绑定本机的IP和端口作为服务器端
UDP不需要Listen(),accept(),直接使用SendTo()/ReceiveFrom()来执行操作。(和TCP的执行方法有区别,因为UDP不需要建立连接,所以在发送前并不知道对方的IP和端口,因此需要指定一个发送的目标位置才能进行正常的发送和接收)
//接收端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//需要引入的命名空间
using System.Net.Socket; //Socket命名空间
using System.Net; //网络命名空间
using System.Threading; //多线程命名空间
public class Server{
private Socket _SocketServer; //Socket
private bool _IsListenContecion; //是否在监听(目的是方便退出)
public Server(){
//定义网络终结点(封装IP与端口),127.0.0.1表示本机,端口尽量大于1024
IPEndPoint endPoint=new IPEndPoint(IPAddress.Parse("127.0.0.1"),1050);
//实例化Socket,协议不同
_SocketServer=new Socket(AddressFamily.InterNetWork,SocketType.Dgram,ProtocolType.Udp);
//服务器端绑定地址
_SocketServer.Bind(endPoint);
EndPoint ep=(EndPoint)endPoint;
while(true){
//准备一个“数据缓存”
byte[] msgArray=new byte[1024*1024]; //最大长度1M空间
//接收客户端发来的数据,返回数据真实的长度
int trueClineMsgLength=_SocketServer.ReceiveFrom(msgArray,ref ep);
//byte数组转String
String strMsg=Encoding.UTF8.GetString(msgArray,0,trueClineMsgLength);
//显示客户端发来的数据
Console.WriteLine("客户端发来的数据"+strMsg);
}
}
static void Main(string[] args){
Server obj=new Server();
}
}
//发送端
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
//需要引入的命名空间
using System.Net.Socket; //Socket命名空间
using System.Net; //网络命名空间
using System.Threading; //多线程命名空间
public class Client{
private Socket _SocketClient; //通讯Socket
private IPEndPoint sertEndPoint; //需要连接的服务器IP与端口信息
public Client(){
//(服务器端)通讯地址与端口号
sertEndPoint=new IPEndPoint(IPAddress.Parse("127.0.0.1"),1050);
//建立客户端的Socket,协议不同
_SocketClient=new Socket(AddressFamily.InterNetWork,SocketType.Dgram,ProtocolType.Udp);
EndPoint ep=(EndPoint)sertEndPoint;
while(true){
//输入信息
string strMsg=Console.ReadLine();
//退出
if(strMSg=="exit"){
break;
}
//字节转换
Byte[] byteArray=Encoding.UTF8.GetBytes(strMsg);
//发送数据
_SocketClient.SendTo(byteArray,ref ep);
Console.WriteLine("我"+strMsg);
}
//关闭连接
_SocketClient.Shutdown(SocketShutdown.Both);
//清理连接资源
_SocketClient、Close();
}
static void Main(string[] args){
Client obj=new Client();
}
}