Socket通信机制

文章目录

    • 什么是Socket?
    • TCP/IP协议族
    • Socket实现原理
    • 命名空间
    • 服务端实现代码
    • 客户端实现代码
    • TcpListener类
    • TcpClient类
    • NetworkStream类
    • TCP与UDP协议的区别

什么是Socket?

Socket是应用层与TCP/IP协议族通信的中间软件抽象层,它是一组接口。在设计模式中,Socket其实就是一个门面模式,它把复杂的TCP/IP协议族隐藏在Socket接口后面,对用户来说,一组简单的接口就是全部,让Socket去组织数据,以符合指定的协议。(见下图)

Socket通信机制_第1张图片
既然是TCP/IP协议族隐藏在Socket接口后面,那么,什么是TCP/IP协议呢?

TCP/IP协议族

TCP/IP(Transmission Control Protocol/Internet Protocol)即传输控制协议/网间协议,不是一个协议,而是包含众多协议的协议集,它是为广域网(WANS)设计的。
UDP(User Data Protocol,用户数据报协议)是与TCP相对应的协议。它是属于TCP/IP协议族中的一种。与TCP协议位于同一层,主要作用:为了在给定的主机上能识别多个目的地址,同时允许多个应用程序在同一台主机上工作并能独立地进行数据包的发送和接收,设计用户数据报协议UDP。UDP使用底层的互联网协议来传送报文,同IP一样提供不可靠的无连接数据包传输服务。它不提供报文到达确认、排序、及流量控制等功能。

Socket实现原理

当A给B打电话,A先拨号,接通后进行对话,对话结束,挂掉电话!这也是Socket的实现原理。A拨号就相当于输入IP找到对方主机,在通过端口号找到应用程序,找到主机也找到也找到端口号就可以实现通信了。(见下图)
Socket通信机制_第2张图片

命名空间

using System.Net;
using System.Net.Sockets;

服务端实现代码

public partial class frmRecive : Form
{
    public frmRecive()
    {
        InitializeComponent();
        Control.CheckForIllegalCrossThreadCalls = false;
    }
    IPAddress IP;//接收IP地址变量
    TcpListener listener;//建立监听器对象,负责监听客户端是否发来连接请求
    TcpClient tcpClient;//主要通过带入主机地址,然后调用Connect进行和服务器点对点的连接,连接成功后通过GetStream方法返回NetworkStream对象
    public void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)//BackgroundWorker控件是用来执行多线程任务的控件,如果想在后台执行一些耗时的操作,监听操作进度并在操作完成时发出信号可以使用BackgroundWorker控件。
    {
        IP = IPAddress.Parse(this.txtIP.Text);//获取自定义ip地址
        listener = new TcpListener(IP, Convert.ToInt32(this.txtPort.Text));//获取自定义端口号
        listener.Start();//开始监听
        this.txtBoxInfo.Text = "服务器启动-" + DateTime.Now.ToLongTimeString() + "\r\n" + this.txtBoxInfo.Text;//提示文字
        tcpClient = listener.AcceptTcpClient();  //负责接收客户端发来的连接请求操作
        this.txtBoxInfo.Text = "连接成功-" + DateTime.Now.ToLongTimeString() + "\r\n" + this.txtBoxInfo.Text;//提示连接成功

        NetworkStream stream = tcpClient.GetStream();//客户端接收传输的流
        byte[] byteArray = new byte[1024];//实例化字节数组,用来存放传输的字节,长度为1024

        while (true)
        {
            int length = stream.Read(byteArray, 0, 1024);//读取流里面的字节数组,并放到byteArray里面,length就是客户端发送的字节数组长度
            string receiveMessage = Encoding.Unicode.GetString(byteArray, 0, length);//将从客户端接收到的字节数组转化为字符串
            this.txtBoxInfo.Text = "接收到:" + receiveMessage + "-" + DateTime.Now.ToLongTimeString() + "\r\n" + this.txtBoxInfo.Text;
        }//提示接收信息
        
    }

    public void BtnSend_Click(object sender, EventArgs e)//能实现服务器端向顾客端发送消息
    {
        if (txtSend.Text!="")
        {
            string message = this.txtSend.Text;
            this.txtBoxInfo.Text = "发送“" + message + "”-" + DateTime.Now.ToLongTimeString() + "\r\n" + this.txtBoxInfo.Text;
            NetworkStream stream = tcpClient.GetStream();//客户端接收传输的流
            byte[] byteArray = Encoding.Unicode.GetBytes(message);//将服务器端发送的消息转为字节数组
            stream.Write(byteArray, 0, byteArray.Length);//发送了字节数组

            txtSend.Text = "";
        }
        
    }

    public void FrmRecive_Load(object sender, EventArgs e)
    {
        if (frmCallOper.message!="")
        {
            MessageBox.Show("有顾客呼叫您,请及时查看!");
        }
        this.backgroundWorker1.RunWorkerAsync();//让backgroundworker开始执行后台操作
    }
}

客户端实现代码

public partial class frmCallOper : DockContent
{
    public frmCallOper()
    {
        InitializeComponent();
        Control.CheckForIllegalCrossThreadCalls = false;
    }

    private void FrmCallOper_Load(object sender, EventArgs e)
    {
        txtBoxInput.Focus();
    }
    TcpClient tcpClient;//建立客户端变量
    public static string message;//静态变量,用于存放消息内容
    private void BtnSend_Click(object sender, EventArgs e)
    {
        if (txtBoxInput.Text!="")
        {
            message = this.txtBoxInput.Text;
            this.txtBoxInfo.Text = "发送“" + message + "”-" + DateTime.Now.ToLongTimeString() + "\r\n" + this.txtBoxInfo.Text;
            NetworkStream stream = tcpClient.GetStream();//客户端接收传输的流
            byte[] byteArray = Encoding.Unicode.GetBytes(message);//将发送的消息转化为字节数组
            stream.Write(byteArray, 0, byteArray.Length);//发送了字节数组

            txtBoxInput.Text = "";
        }
    }


    private void PicCall_Click(object sender, EventArgs e)
    {
        tcpClient = new TcpClient();//实例化了客户端
        try
        {
            tcpClient.Connect("192.168.96.98", 7890);//设立连接的ip与端口号
            this.txtBoxInfo.Text = "呼叫成功-" + DateTime.Now.ToLongTimeString() + "\r\n" + this.txtBoxInfo.Text;
            this.backgroundWorker1.RunWorkerAsync();//让backgroundworker开始执行操作
        }
        catch (Exception ex)
        {

            MessageBox.Show("呼叫失败-" + ex.Message);
        }
    }

    private void PicCall_MouseEnter(object sender, EventArgs e)
    {
        toolTip1.SetToolTip(picCall, "呼叫网管");
    }

    private void TxtBoxInput_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.KeyCode == Keys.Enter)//回车键触发发送按钮
        {
            this.BtnSend_Click(sender, e);
        }
    }

    private void BackgroundWorker1_DoWork(object sender, DoWorkEventArgs e)
    {
        NetworkStream stream = tcpClient.GetStream();//用来接收网络中传输的流
        byte[] byteArray = new byte[1024];//实例化字节数组

        while (true)
        {
            int length = stream.Read(byteArray, 0, 1024);//会把流里面的字节数组 放到byteArray里面,length就是客户端发送的字节数组长度
            string receiveMessage = Encoding.Unicode.GetString(byteArray, 0, length);//将字节数组转化为字符串格式
            this.txtBoxInfo.Text = "接收到:" + receiveMessage + "-" + DateTime.Now.ToLongTimeString() + "\r\n" + this.txtBoxInfo.Text;
        }
    }
}

TcpListener类

此类也是微软基于Tcp封装类,用于监听服务端或客户端的连接请求,一旦有连接请求信息,立刻交给TcpClient的AcceptTcpClient方法捕获,Start方法用于开始监听。

TcpClient类

此类是微软基于Tcp封装类,用于简化Tcp客户端的开发,主要通过构造带入主机地址或IPEndPonint对象,然后调用Connect进行和服务器点对点的连接,连接成功后通过GetStream方法返NetworkStream对象。

NetworkStream类

NetworkStream:顾名思义,在网络中传输的流,那既然是在网络中传输的,一定有协议去约束它,也就是TCP/IP协议。如果服务器和客户端是基于TCP连接的 ,他们之间能够依靠稳定的字节相互传输信息,这就是NetworkStream的作用。

Tips:

  • NetworkStream只能用在具有Tcp/Ip协议之中,如果用在UDP中编译不报错,会报异常。
  • NetworkStream是面向连接的
  • 在网络中利用流的形式传递信息
  • 必须借助Socket,或使用一些返回的返回值,例如TcpClient的GetStream方法
  • 用法和普通流方法一样,但具有特殊性

TCP与UDP协议的区别

TCP:

1 TCP是面向连接的通信协议,通过三次握手建立连接

2 TCP提供的是一种可靠的数据流服务,采用“带重传的肯定确认”技术来实现传输的可靠性

UDP:

1 UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送

2 UDP通讯时不需要接收方确认,属于不可靠的传输,可能会出丢包现象,实际应用中要求在程序员编程验证

3 由于上述2点的关系,UDP传输速度更快,但是安全性比较差,很容易发生未知的错误,所以NetworkStream无法使用在UDP的功能上

你可能感兴趣的:(★计算机实用小技巧)