精华内容
下载资源
问答
  • c#socket教程
    2021-05-21 10:36:01

    https://www.xin3721.com/eschool/python.html

    本文实例讲述了C# Socket网络编程技巧。分享给大家供大家参考。具体分析如下:

    客户端要连接服务器:首先要知道服务器的IP地址。而服务器里有很多的应用程序,每一个应用程序对应一个端口号

    所以客户端想要与服务器中的某个应用程序进行通信就必须要知道那个应用程序的所在服务器的IP地址,及应用程序所对应的端口号

    TCP协议:安全稳定,一般不会发生数据丢失,但是效率低。利用TCP发生数据一般经过3次握手(所有效率低,自己百度三次握手)

    UDP协议:快速,效率高,但是不稳定,容易发生数据丢失(没有经过三次握手,不管服务器有空没空,信息全往服务器发,所有效率搞,但服务器忙的时候就没办法处理你的数据,容易造成数据丢失,不稳定)

    复制代码 代码如下:

    using System;

    using System.Collections.Generic;

    using System.ComponentModel;

    using System.Data;

    using System.Drawing;

    using System.Linq;

    using System.Text;

    using System.Windows.Forms;

    using System.Net.Sockets;

    using System.Net;

    using System.Threading;

    namespace Socket通信

    {

    public partial class Form1 : Form

    {

    public Form1()

    {

    InitializeComponent();

    this.txtPort.Text = "5000";

    this.txtIp.Text = "192.168.137.1";

    }

    private void btnStart_Click(object sender, EventArgs e)

    {

    //当点击开始监听的时候,在服务器端创建一个负责监听IP地址跟端口号的Socket

    Socket socketWatch = new Socket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);

    //Any:提供一个 IP 地址,指示服务器应侦听所有网络接口上的客户端活动。此字段为只读。

    IPAddress ip = IPAddress.Any;

    //创建端口号对象;将txtPort.Text控件的值设为服务端的端口号

    IPEndPoint point = new IPEndPoint(ip, Convert.ToInt32(txtPort.Text));

    //监听

    socketWatch.Bind(point);

    ShowMsg("监听成功");

    socketWatch.Listen(10);//连接队列的最大长度 ;即:一个时间点内最大能让几个客户端连接进来,超过长度就进行排队

    //等待客户端连接;Accept()这个方法能接收客户端的连接,并为新连接创建一个负责通信的Socket

    Thread th = new Thread(Listen); //被线程执行的方法如果有参数的话,参数必须是object类型

    Control.CheckForIllegalCrossThreadCalls = false; //因为.net不允许跨线程访问的,所以这里取消跨线程的检查。.net不检查是否有跨线程访问了,所有就不会报: “从不是创建控件“txtLog”的线程访问它” 这个错误了,从而实现了跨线程访问

    th.IsBackground = true; //将th这个线程设为后台线程。

    //Start(object parameter); parameter:一个对象,包含线程执行的方法要使用的数据,即线程执行Listen方法,Listen的参数

    th.Start(socketWatch);  //这个括号里的参数其实是Listen()方法的参数。因为Thread th = new Thread(Listen)这个括号里只能写方法名(函数名) 但是Listen()方法是有参数的,所有就要用Start()方法将它的参数添加进来

    }

    ///

    /// 等待客户端连接,如果监控到有客户端连接进来就创建一个与之通信的Socket

    ///

    ///

    void Listen(object o) //这里为什么不直接传递Socket类型的参数呢? 原因是:被线程执行的方法如果有参数的话,参数必须是object类型

    {

    Socket socketWatch = o as Socket;

    while (true) //为什么这里要有个while循环?因为当一个人连接进来的时候创建了与之通信的Socket后就程序就会往下执行了,就不会再回来为第二个人的连接创建负责通信的Socket了。(应该是每个人(每个客户端)创建一个与之通信的Socket)所以要写在循环里。

    {

    //等待客户端连接;Accept()这个方法能接收客户端的连接,并为新连接创建一个负责通信的Socket

    Socket socketSend = socketWatch.Accept();

    dic.Add(socketSend.RemoteEndPoint.ToString(), socketSend); //(根据客户端的IP地址和端口号找负责通信的Socket,每个客户端对应一个负责通信的Socket),ip地址及端口号作为键,将负责通信的Socket作为值填充到dic键值对中。

    //我们通过负责通信的这个socketSend对象的一个RemoteEndPoint属性,能够拿到远程连过来的客户端的Ip地址跟端口号

    ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + "连接成功");//效果:192.168.1.32:连接成功

    comboBox1.Items.Add(socketSend.RemoteEndPoint.ToString()); //将连接过来的每个客户端都添加到combBox控件中。

    //客户端连接成功后,服务器应该接收客户端发来的消息。

    Thread getdata = new Thread(GetData);

    getdata.IsBackground = true;

    getdata.Start(socketSend);

    }

    }

    Dictionary dic = new Dictionary();

    ///

    /// 不停的接收客户端发送过来的消息

    ///

    ///

    void GetData(object o)

    {

    while (true)

    {

    Socket socketSend = o as Socket;

    //将客户端发过来的数据先放到一个字节数组里面去

    byte[] buffer = new byte[1024 * 1024 * 2]; //创建一个字节数组,字节数组的长度为2M

    //实际接收到的有效字节数; (利用Receive方法接收客户端传过来的数据,然后把数据保存到buffer字节数组中,返回一个接收到的数据的长度)

    int r = socketSend.Receive(buffer);

    if (r == 0) //如果接收到的有效字节数为0 说明客户端已经关闭了。这时候就跳出循环了。

    {

    //只有客户端给用户发消息,不可能是发0个长度的字节。即便发空消息,空消息也是有过个长度的。所有接收到的有效字节长度为0就代表客户端已经关闭了

    break;

    }

    //将buffer这个字节数组里面的数据按照UTF8的编码,解码成我们能够读懂的的string类型,因为buffer这个数组的实际存储数据的长度是r个 ,所以从索引为0的字节开始解码,总共解码r个字节长度。

    string str = Encoding.UTF8.GetString(buffer, 0, r);

    ShowMsg(socketSend.RemoteEndPoint.ToString() + ":" + str);

    }

    }

    private void ShowMsg(string str)

    {

    txtLog.AppendText(str + "\r\n"); //将str这个字符串添加到txtLog这个文本框中。

    }

    ///

    /// 服务端给客户端发信息

    ///

    ///

    ///

    private void btnSend_Click_1(object sender, EventArgs e)

    {

    if (comboBox1.SelectedItem == null) //如果comboBox控件没有选中值。就提示用户选择客户端

    {

    MessageBox.Show("请选择客户端");

    return;

    }

    string str = txtMes.Text; //获取用户输入的内容 (服务端要给客户端发的信息)

    byte[] strByte = Encoding.Default.GetBytes(str); //将信息转换成二进制字节数组

    string getIp = comboBox1.SelectedItem as string; //comboBox存储的是客户端的(ip+端口号)

    Socket socketSend = dic[getIp] as Socket; //根据这个(ip及端口号)去dic键值对中找对应 赋值与客户端通信的Socket【每个客户端都有一个负责与之通信的Socket】

    socketSend.Send(strByte); //将信息发送到客户端

    }

    }

    }

    开打开始命令  cmd   telnet 10.18.16.46 5000    即telnet 服务器ip地址  绑定的端口号

    希望本文所述对大家的C#程序设计有所帮助。

    更多相关内容
  • 入门级C# Socket编程实现

    千次阅读 多人点赞 2022-03-28 16:18:09
    文章简单介绍了Socket的概念和作用,并详细介绍了如何使用C#语言实现Socket编程,实现进程之间的数据传输,可以拓展成窗口功能,文章中包含了服务器端和客户端完整代码,以及非常详细的Socket对象方法介绍和示例以及...

    说明:本篇推文侧重讲解C#的Socket编程实现,里面有完整实现的GIF动图,大家可以先去看一下,Socket原理介绍的不多,可能有很多不足的地方,原理方面大家可以去找其他资料看一下。
    Socket编程这部分我主要着重介绍了Socket编程用到的一些相关类、方法以及实现步骤,不断地分步骤介绍,是为了能够加深印象也方便大家理解并复刻这款简单软件,大家学会了可以自己去拓展功能或者嵌入其他项目中,socket相关类和方法可能会有点冗余,大家可以直接跳到完整的实现代码去研究学习。

    一、Socket套接字

    Socket的定义

    套接字(Socket),是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信的一端,提供了应用层进程利用网络协议交换数据的机制。从所处的地位来讲,套接字上联应用进程,下联网络协议栈,是应用程序通过网络协议进行通信的接口,是应用程序与网络协议栈进行交互的接口,Socket所处的位置大概是下面这样的。
    在这里插入图片描述
    五层架构使用的协议
    我们可以将Socket联想成是由两个Socket对象搭建的成的一根通信管道,管道的两端是这两个Socket对象,而这根管道的连接的是两台主机的应用进程。假设A、B两台主机上的应用进程要互相发送数据,那么我们就可以用Socket打造一条连接A、B主机进程的管道,A主机进程使用Socket对象把数据往管道里面一丢,然后B主机进程就可以使用Socket对象把数据给拿出来,反之当B主机进程要给A主机进程发送数据的时候也是通过操作Socket对象就可以简单实现数据的发送和接收。
    在这里插入图片描述
    学过计算机网络的同学都知道数据在因特网上传输并不像上面说的那么简单,根据经典的五层协议体系结构(如下图),一个报文从一个进程传输到另一个进程需要经过自上到下层层协议的封装,然后转换成比特流通过物理层,途径多个路由,最后才能到到达目的主机【这里要用到的IP来标定网络上特定的主机】,然后再在目的主机上经过层层解析最终根据端口号把报文传输到目的进程,而使用Socket就不需要我们自己层层封装信息,也不用管信息是如何在网络上传输的,我们只需要绑定IP地址和应用进程号,使用Socket对象就可以实现进程之间数据的发送和接收,大大缩减了我们的工作,非常的nice。
    这里推荐一个计算机网络课程,图文并茂讲计算机网络巨通俗易懂
    https://www.bilibili.com/video/BV1c4411d7jb?share_source=copy_web
    计算机网络体系

    二、Socket编程

    通过上面的简单介绍,我们能大致了解Socket的作用是完成两个应用程序之间的数据传输,我们只要知道要通信的两台主机的IP地址和进程的端口号,然后可以用Socket让这两个进程进行通信,接下来我们就进入正题,使用C#进行Socket编程,完成本地两个进程的通信

    1.效果展示

    在这里插入图片描述

    2.Socket通信基本流程图

    在这里插入图片描述
    根据上面的流程图可以知道使用socket实现通信大致需要完成以下几个步骤:
    服务器端:
    第一步:建立一个用于通信的Socket对象
    第二步:使用bind绑定IP地址和端口号
    第三步:使用listen监听客户端
    第四步:使用accept中断程序直到连接上客户端
    第五步:接收来自客户端的请求
    第六步:返回客户端需要的数据
    第七步:如果接收到客户端已关闭连接信息就关闭服务器端

    客户端:
    第一步:建立一个用于通信的Socket对象
    第二步:根据指定的IP和端口connet服务器
    第三步:连接成功后向服务器端发送数据请求
    第四步:接收服务器返回的请求数据
    第五步:如果还需要请求数据继续发送请求
    第六步:如果不需要请求数据就关闭客户端并给服务器发送关闭连接信息

    3.Socket编程常用类和方法

    相关类

    (1) IPAddress:包含了一个IP地址[提供 Internet 协议 (IP) 地址]

    //这里的IP是long类型的,这里使用Parse()可以将string类型数据转成IPAddress所需要的数据类型
    IPAddress IP = IPAddress.Parse();
    

    (2) IPEndPoint:包含了一对IP地址和端口号

    /*public IPEndPoint(IPAddress address, int port);*/
    IPEndPoint endPoint = new IPEndPoint(ip,port);	//处理IP地址和端口的封装类
    

    (3)Encoding.ASCII:编码转换

    Encoding.ASCII.GetBytes()	//将字符串转成字节
    Encoding.ASCII.GetString()	//将字节转成字符串
    

    (4)获取当前时间

    DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ")
    

    Socket编程函数【作用+示例】:

    (1)Socket()

    • 创建Socket对象,构造函数需要输入三个参数,创建客户端和服务器端Socket对象示例如下
    Socket ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    Socket ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
    

    Socket构造函数参数

    • AddressFamily指定Socket用来解析地址的寻址方案
    • SocketType定义要打开的Socket的类型
    • ProtocolType:向Windows Sockets API通知所请求的协议

    (2)Bind()

    • 绑定一个本地的IP和端口号,参数是一个绑定了IP和端口号的IPEndPoint对象
    ServerSocket.Bind(new IPEndPoint(ip,port));
    或者
    IPEndPoint ipEndPoint = new IPEndPoint(ip,port)
    ServerSocket.Bind(ipEndPoint);
    

    (3)Listen()

    • 让Socket侦听传入的连接,参数为指定侦听队列的容量,
    ServerSocket.Listen(10);
    

    (4)Connect()

    • 建立与远程主机的连接
    ClientSocket.Connect(ipEndPoint);
    

    (5)Accept()

    • 接收连接并返回一个新的Socket,Accept会中断程序,直到有客户端连接
    Socket socket = ServerSocket.Accept();
    

    (6)Send()

    • 输出数据到Socket
    //Encoding.ASCII.GetBytes()将字符串转成字节
    byte[] message = Encoding.ASCII.GetBytes("Connect the Server"); //通信时实际发送的是字节数组,所以要将发送消息转换字节
    ClientSocket.Send(message);
    socket.Send(message);
    

    (7)Receive()

    • 从Socket中读取数据
    byte[] receive = new byte[1024];
    int length = ClientSocket.Receive(receive); // length 接收字节数组长度
    int length = socket.Receive(receive);
    

    (8)Close()

    • 关闭Socket,销毁连接
    socket.Close()
    ClientSocket.Close()
    
    类型函数
    服务器socketBind()
    Listen()
    Accept()
    客户端socketConnect()
    公共socketReceive()
    Send()
    Close()

    4.编程实现步骤

    (1)UI设计

    服务器端:
    在这里插入图片描述
    客户端:
    在这里插入图片描述
    下面是我给各组件设置的name值,客户端和服务器端除了Button有一个不一样其他组件设置的name值都是一样的

    组件Name
    TextBoxtextBox_Addr
    textBox_Port
    RichTextBoxrichTextBox_Receive
    richTextBox_Send
    Buttonbutton_Accpet
    button_Connect
    button_Close
    button_Send

    (2)服务器端:

    实现步骤:
    第一步:创建一个用于监听连接的Socket对象;

    Socket ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);     //创建用于监听连接的套接字
    

    第二步:用指定的端口号和服务器的ip建立一个IPEndPoint对象;

    IPAddress IP = IPAddress.Parse(textBox_Addr.Text);	//获取输入的IP地址
    int Port = int.Parse(textBox_Port.Text);	//获取输入的端口号
    //IPAddress ip = IPAddress.Any;
    IPEndPoint iPEndPoint = new IPEndPoint(IP, Port);	
    

    第三步:用socket对象的Bind()方法绑定IPEndPoint;

    ServerSocket.Bind(iPEndPoint);
    

    第四步:用socket对象的Listen()方法开始监听;

    ServerSocket.Listen(10);
    

    第五步:建立与客户端的连接,用socket对象的Accept()方法创建用于和客户端进行通信的socket对象;(因为accept会中断程序,所以我使用线程来实现客户端的接入)

    Socket socket = socketAccept.Accept();
    

    第六步:接收来自客户端的信息(我是使用线程来实现数据的接收)

    byte[] recieve = new byte[1024];
    int len = socket.Receive(recieve);
    richTextBox_Recieve.Text += Encoding.ASCII.GetString(recieve, 0, len);  //将字节数据根据ASCII码转成字符串
    

    第七步:向客户端发送信息

    byte[] send = new byte[1024];
    send = Encoding.ASCII.GetBytes(richTextBox_Send.Text);    //将字符串转成字节格式发送
    socket.Send(send);  //调用Send()向客户端发送数据
    

    第八步:关闭Socket

    socket.Close();     //关闭用于通信的套接字          
    ServerSocket.Close();   //关闭用于连接的套接字
    socketAccept.Close();   //关闭与客户端绑定的套接字
    th1.Abort();    //关闭线程1
    

    具体实现代码:
    (1)因为有使用线程,为了防止出错,在初始化的时候关闭检测

    private void Form1_Load(object sender, EventArgs e)
            {
                Control.CheckForIllegalCrossThreadCalls = false;    //执行新线程时跨线程资源访问检查会提示报错,所以这里关闭检测
            }
    

    (2)建立连接,首先创建一个ServerSocket将连接需要的参数都设置好并监听连接,然后创建线程Accept客户的连接

     		/*****************************************************************/
            #region 连接客户端(绑定按钮事件)
            private void button_Accpet_Click(object sender, EventArgs e)
            {
    
                ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);     //创建用于通信的套接字
                
                richTextBox_Receive.Text += "正在连接...\n";
                button_Accpet.Enabled = false;  //禁止操作接收按钮
               
                //1.绑定IP和Port
                IPAddress IP = IPAddress.Parse(textBox_Addr.Text);
                int Port = int.Parse(textBox_Port.Text);
    
                //IPAddress ip = IPAddress.Any;
                IPEndPoint iPEndPoint = new IPEndPoint(IP, Port);
    
                try
                {
                    //2.使用Bind()进行绑定
                    ServerSocket.Bind(iPEndPoint);
                    //3.开启监听
                    //Listen(int backlog); backlog:监听数量 
                    ServerSocket.Listen(10);
    
                    /*
                     * tip:
                     * Accept会阻碍主线程的运行,一直在等待客户端的请求,
                     * 客户端如果不接入,它就会一直在这里等着,主线程卡死
                     * 所以开启一个新线程接收客户单请求
                     */
    
                    //开启线程Accept进行通信的客户端socket
                    th1 = new Thread(Listen);   //线程绑定Listen函数
                    th1.IsBackground = true;    //运行线程在后台执行
                    th1.Start(ServerSocket);    //Start里面的参数是Listen函数所需要的参数,这里传送的是用于通信的Socket对象
                    Console.WriteLine("1");
                }
                catch
                {
                    MessageBox.Show("服务器出问题了");
                }
            }
            #endregion
            /*****************************************************************/
    
    		/*****************************************************************/
            #region 建立与客户端的连接
            void Listen(Object sk) 
            {
                socketAccept = sk as Socket;    //创建一个与客户端对接的套接字
                
                try
                {
                   while (true) 
                   {
                       //GNFlag如果为1就进行中断连接,使用在标志为是为了保证能够顺利关闭服务器端
                       /*
                        * 当客户端关闭一次后,如果没有这个标志位会使得服务器端一直卡在中断的位置
                        * 如果服务器端一直卡在中断的位置就不能顺利关闭服务器端
                        */
    
                        //4.阻塞到有client连接
                        socket = socketAccept.Accept();
    
                        CFlag = 0;  //连接成功,将客户端关闭标志设置为0
                        SFlag = 1;  //当连接成功,将连接成功标志设置为1
    
                        richTextBox_Receive.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + textBox_Addr.Text + "连接成功";
                        richTextBox_Receive.Text += "\r\n";
    
                        //开启第二个线程接收客户端数据
                        th2 = new Thread(Receive);  //线程绑定Receive函数
                        th2.IsBackground = true;    //运行线程在后台执行
                        th2.Start(socket);    //Start里面的参数是Listen函数所需要的参数,这里传送的是用于通信的Socket对象
                   }
                }
                catch 
                {
                    //MessageBox.Show("没有连接上客户端");   
                }
            }
            #endregion
            /*****************************************************************/
    

    (3)连接上客户端后,使用线程接收客户端数据,参数是Accept到的Socket对象

    /*****************************************************************/
            #region 接收客户端数据
            void Receive(Object sk)
            {
                socket = sk as Socket;  //创建用于通信的套接字
    
                while (true)
                {
                    try
                    {
                        if (CFlag == 0 && SFlag == 1)
                        {
                            //5.接收数据
                            byte[] recieve = new byte[1024];
                            int len = socket.Receive(recieve);
    
                            //6.打印接收数据
                            if (recieve.Length > 0)
                            {
                                //如果接收到客户端停止的标志
                                if (Encoding.ASCII.GetString(recieve, 0, len) == "*close*")
                                {
                                    richTextBox_Receive.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + "客户端已退出" + "\n";
                                    CFlag = 1;      //将客户端关闭标志设置为1
    
                                    break;      //退出循环
                                }
    
                                //打印接收数据
                                richTextBox_Receive.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + "接收:";
                                richTextBox_Receive.Text += Encoding.ASCII.GetString(recieve, 0, len);  //将字节数据根据ASCII码转成字符串
                                richTextBox_Receive.Text += "\r\n";
                            }
                        }
                        else
                        {
                            break;  //跳出循环
                        } 
                    }
                    catch
                    {
                        MessageBox.Show("收不到信息");
                    }  
                }  
            }
            #endregion
            /*****************************************************************/
    

    (4)向客户端发送数据

            /*****************************************************************/
            #region 向客户端发送数据
            private void button_Send_Click(object sender, EventArgs e)
            {
                //SFlag标志连接成功,同时当客户端是打开的时候才能发送数据
                if(SFlag == 1 && CFlag == 0)
                {
                    byte[] send = new byte[1024];
                    send = Encoding.ASCII.GetBytes(richTextBox_Send.Text);    //将字符串转成字节格式发送
                    socket.Send(send);  //调用Send()向客户端发送数据
    
                    //打印发送时间和发送的数据
                    richTextBox_Receive.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + "发送:";
                    richTextBox_Receive.Text += richTextBox_Send.Text + "\n";
                    richTextBox_Send.Clear();   //清除发送框
                } 
            }
            #endregion
            /*****************************************************************/
    

    (5)关闭服务器端

    /*****************************************************************/
            #region 关闭服务器端
            private void button_Close_Click(object sender, EventArgs e)
            {
                //若连接上了客户端需要关闭线程2和socket,没连接上客户端直接关闭线程1和其他套接字
                if(CFlag == 1)
                {
                    th2.Abort();        //关闭线程2
                    socket.Close();     //关闭用于通信的套接字
                }
                
                ServerSocket.Close();   //关闭用于连接的套接字
                socketAccept.Close();   //关闭与客户端绑定的套接字
                th1.Abort();    //关闭线程1
    
                CFlag = 0;  //将客户端标志重新设置为0,在进行连接时表示是打开的状态
                SFlag = 0;  //将连接成功标志程序设置为0,表示退出连接
                button_Accpet.Enabled = true;
                richTextBox_Receive.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ");
                richTextBox_Receive.Text += "服务器已关闭" + "\n";
                MessageBox.Show("服务器已关闭");
            }
            #endregion
            /*****************************************************************/
    

    (3)客户端:

    第一步:建立一个Socket对象;

    Socket ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);     //声明负责通信的套接字
    

    第二步:用指定的端口号和服务器的ip建立一个IPEndPoint对象;

    IPAddress IP = IPAddress.Parse(textBox_Addr.Text);      //获取设置的IP地址
    int Port = int.Parse(textBox_Port.Text);       //获取设置的端口号
    IPEndPoint iPEndPoint = new IPEndPoint(IP,Port);    //指定的端口号和服务器的ip建立一个IPEndPoint对象
    

    第三步:用socket对像的Connect()方法以上面建立的EndPoint对象做为参数,向服务器发出连接请求;

    ClientSocket.Connect(iPEndPoint);
    

    第四步:如果连接成功,就用socket对象的Send()方法向服务器发送信息;

    byte[] send = new byte[1024];
    send = Encoding.ASCII.GetBytes(richTextBox_Send.Text);  //将文本内容转换成字节发送
    ClientSocket.Send(send);    //调用Send()函数发送数据
    

    第五步:用socket对象的Receive()方法接受服务器的信息 ;

    byte[] receive = new byte[1024];
    ClientSocket.Receive(receive);  //调用Receive()接收字节数据
    

    第六步:通信结束后关闭socket;

    ClientSocket.Close();   //关闭套接字
    

    具体代码实现
    (1)使用线程,为了防止出错,在初始化的时候关闭检测

    private void Form1_Load(object sender, EventArgs e)
            {
                Control.CheckForIllegalCrossThreadCalls = false;    //执行新线程时跨线程资源访问检查会提示报错,所以这里关闭检测
            }
    

    (2)建立与服务器端的连接

    /*****************************************************************/
            #region 连接服务器端
            private void button_Connect_Click(object sender, EventArgs e)
            {
                ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);     //声明负责通信的套接字
                
                richTextBox_Recieve.Text += "正在连接...\n";
                
                IPAddress IP = IPAddress.Parse(textBox_Addr.Text);      //获取设置的IP地址
                int Port = int.Parse(textBox_Port.Text);       //获取设置的端口号
                IPEndPoint iPEndPoint = new IPEndPoint(IP,Port);    //指定的端口号和服务器的ip建立一个IPEndPoint对象
    
                try
                {  
                    ClientSocket.Connect(iPEndPoint);       //用socket对象的Connect()方法以上面建立的IPEndPoint对象做为参数,向服务器发出连接请求
                    SFlag = 1;  //若连接成功将标志设置为1
                        
                    richTextBox_Recieve.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + textBox_Addr.Text + "连接成功" + "\n";
                    button_Connect.Enabled = false;     //禁止操作连接按钮
                    
                    //开启一个线程接收数据
                    th1 = new Thread(Receive);
                    th1.IsBackground = true;
                    th1.Start(ClientSocket);    
                }
                catch 
                {
                    MessageBox.Show("服务器未打开");
                }    
            }
            #endregion
            /*****************************************************************/
    

    (3)若连接成功,创建线程实现接收服务器端的数据

    /*****************************************************************/
            #region 接收服务器端数据
            void Receive(Object sk)
            {
                Socket socketRec = sk as Socket;
    
                while (true)
                {
                    //5.接收数据
                    byte[] receive = new byte[1024];
                    ClientSocket.Receive(receive);  //调用Receive()接收字节数据
    
                    //6.打印接收数据
                    if (receive.Length > 0)
                    {
                        richTextBox_Recieve.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + "接收:";   //打印接收时间
                        richTextBox_Recieve.Text += Encoding.ASCII.GetString(receive);  //将字节数据根据ASCII码转成字符串
                        richTextBox_Recieve.Text += "\r\n";
                    }
                }
            }
            #endregion
            /*****************************************************************/
    

    (4)向服务器端发送数据(于send按钮进行事件绑定)

    /*****************************************************************/
            #region 向服务器端发送数据
            private void button_Send_Click(object sender, EventArgs e)
            {
                //只有连接成功了才能发送数据,接收部分因为是连接成功才开启线程,所以不需要使用标志
                if (SFlag == 1)
                {
                    byte[] send = new byte[1024];
                    send = Encoding.ASCII.GetBytes(richTextBox_Send.Text);  //将文本内容转换成字节发送
                    ClientSocket.Send(send);    //调用Send()函数发送数据
    
                    richTextBox_Recieve.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + "发送:";   //打印发送数据的时间
                    richTextBox_Recieve.Text += richTextBox_Send.Text + "\n";   //打印发送的数据
                    richTextBox_Send.Clear();   //清空发送框
                }
            }
            #endregion
            /*****************************************************************/
    

    (5)关闭客户端

    		/*****************************************************************/
            #region 关闭客户端
            private void buttonClose_Click(object sender, EventArgs e)
            {
                //保证是在连接状态下退出
                if (SFlag == 1)
                {
                    byte[] send = new byte[1024];
                    send = Encoding.ASCII.GetBytes("*close*");  //关闭客户端时给服务器发送一个退出标志
                    ClientSocket.Send(send);
                    
                    th1.Abort();    //关闭线程
                    ClientSocket.Close();   //关闭套接字
                    
                    button_Connect.Enabled = true;  //允许操作按钮
                    SFlag = 0;  //客户端退出后将连接成功标志程序设置为0
                    richTextBox_Recieve.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ");
                    richTextBox_Recieve.Text += "客户端已关闭" + "\n";
                    MessageBox.Show("已关闭连接");
                }
            }
            #endregion
            /*****************************************************************/
    

    五、服务器端完整代码

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Net;
    using System.Net.Sockets;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Server
    {
        public partial class Form1 : Form
        {
            //这里声明多个套接字是为了在连接,接收数据,发送数据的函数中不发生混乱,同时方便关闭
            public static Socket ServerSocket;    //声明用于监听的套接字
            public static Socket socketAccept;    //声明绑定了客户端的套接字   
            public static Socket socket;    //声明用于与某一个客户端通信的套接字
            
            public static int SFlag = 0;    //连接成功标志
            public static int CFlag = 0;    //客户端关闭的标志
    
            Thread th1;     //声明线程1
            Thread th2;     //声明线程2
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            {
                Control.CheckForIllegalCrossThreadCalls = false;    //执行新线程时跨线程资源访问检查会提示报错,所以这里关闭检测
            }
    
            /*****************************************************************/
            #region 连接客户端
            private void button_Accpet_Click(object sender, EventArgs e)
            {
    
                ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);     //创建用于通信的套接字
                
                richTextBox_Receive.Text += "正在连接...\n";
                button_Accpet.Enabled = false;  //禁止操作接收按钮
               
                //1.绑定IP和Port
                IPAddress IP = IPAddress.Parse(textBox_Addr.Text);
                int Port = int.Parse(textBox_Port.Text);
    
                //IPAddress ip = IPAddress.Any;
                IPEndPoint iPEndPoint = new IPEndPoint(IP, Port);
    
                try
                {
                    //2.使用Bind()进行绑定
                    ServerSocket.Bind(iPEndPoint);
                    //3.开启监听
                    //Listen(int backlog); backlog:监听数量 
                    ServerSocket.Listen(10);
    
                    /*
                     * tip:
                     * Accept会阻碍主线程的运行,一直在等待客户端的请求,
                     * 客户端如果不接入,它就会一直在这里等着,主线程卡死
                     * 所以开启一个新线程接收客户单请求
                     */
    
                    //开启线程Accept进行通信的客户端socket
                    th1 = new Thread(Listen);   //线程绑定Listen函数
                    th1.IsBackground = true;    //运行线程在后台执行
                    th1.Start(ServerSocket);    //Start里面的参数是Listen函数所需要的参数,这里传送的是用于通信的Socket对象
                    Console.WriteLine("1");
                }
                catch
                {
                    MessageBox.Show("服务器出问题了");
                }
            }
            #endregion
            /*****************************************************************/
    
            /*****************************************************************/
            #region 建立与客户端的连接
            void Listen(Object sk) 
            {
                socketAccept = sk as Socket;    //创建一个与客户端对接的套接字
                
                try
                {
                   while (true) 
                   {
                       //GNFlag如果为1就进行中断连接,使用在标志为是为了保证能够顺利关闭服务器端
                       /*
                        * 当客户端关闭一次后,如果没有这个标志位会使得服务器端一直卡在中断的位置
                        * 如果服务器端一直卡在中断的位置就不能顺利关闭服务器端
                        */
    
                        //4.阻塞到有client连接
                        socket = socketAccept.Accept();
    
                        CFlag = 0;  //连接成功,将客户端关闭标志设置为0
                        SFlag = 1;  //当连接成功,将连接成功标志设置为1
    
                        richTextBox_Receive.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + textBox_Addr.Text + "连接成功";
                        richTextBox_Receive.Text += "\r\n";
    
                        //开启第二个线程接收客户端数据
                        th2 = new Thread(Receive);  //线程绑定Receive函数
                        th2.IsBackground = true;    //运行线程在后台执行
                        th2.Start(socket);    //Start里面的参数是Listen函数所需要的参数,这里传送的是用于通信的Socket对象
                   }
                }
                catch 
                {
                    //MessageBox.Show("没有连接上客户端");   
                }
            }
            #endregion
            /*****************************************************************/
    
            /*****************************************************************/
            #region 接收客户端数据
            void Receive(Object sk)
            {
                socket = sk as Socket;  //创建用于通信的套接字
    
                while (true)
                {
                    try
                    {
                        if (CFlag == 0 && SFlag == 1)
                        {
                            //5.接收数据
                            byte[] recieve = new byte[1024];
                            int len = socket.Receive(recieve);
    
                            //6.打印接收数据
                            if (recieve.Length > 0)
                            {
                                //如果接收到客户端停止的标志
                                if (Encoding.ASCII.GetString(recieve, 0, len) == "*close*")
                                {
                                    richTextBox_Receive.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + "客户端已退出" + "\n";
                                    CFlag = 1;      //将客户端关闭标志设置为1
    
                                    break;      //退出循环
                                }
    
                                //打印接收数据
                                richTextBox_Receive.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + "接收:";
                                richTextBox_Receive.Text += Encoding.ASCII.GetString(recieve, 0, len);  //将字节数据根据ASCII码转成字符串
                                richTextBox_Receive.Text += "\r\n";
                            }
                        }
                        else
                        {
                            break;  //跳出循环
                        } 
                    }
                    catch
                    {
                        MessageBox.Show("收不到信息");
                    }  
                }  
            }
            #endregion
            /*****************************************************************/
    
            /*****************************************************************/
            #region 向客户端发送数据
            private void button_Send_Click(object sender, EventArgs e)
            {
                //SFlag标志连接成功,同时当客户端是打开的时候才能发送数据
                if(SFlag == 1 && CFlag == 0)
                {
                    byte[] send = new byte[1024];
                    send = Encoding.ASCII.GetBytes(richTextBox_Send.Text);    //将字符串转成字节格式发送
                    socket.Send(send);  //调用Send()向客户端发送数据
    
                    //打印发送时间和发送的数据
                    richTextBox_Receive.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + "发送:";
                    richTextBox_Receive.Text += richTextBox_Send.Text + "\n";
                    richTextBox_Send.Clear();   //清除发送框
                } 
            }
            #endregion
            /*****************************************************************/
    
            /*****************************************************************/
            #region 关闭服务器端
            private void button_Close_Click(object sender, EventArgs e)
            {
                //若连接上了客户端需要关闭线程2和socket,没连接上客户端直接关闭线程1和其他套接字
                if(CFlag == 1)
                {
                    th2.Abort();        //关闭线程2
                    socket.Close();     //关闭用于通信的套接字
                }
                
                ServerSocket.Close();   //关闭用于连接的套接字
                socketAccept.Close();   //关闭与客户端绑定的套接字
                th1.Abort();    //关闭线程1
    
                CFlag = 0;  //将客户端标志重新设置为0,在进行连接时表示是打开的状态
                SFlag = 0;  //将连接成功标志程序设置为0,表示退出连接
                button_Accpet.Enabled = true;
                richTextBox_Receive.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ");
                richTextBox_Receive.Text += "服务器已关闭" + "\n";
                MessageBox.Show("服务器已关闭");
            }
            #endregion
            /*****************************************************************/
    
            /*****************************************************************/
            #region 点击enter发送数据
            private void richTextBox_Send_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.KeyCode == Keys.Enter)//如果输入的是回车键  
                {
                    this.button_Send_Click(sender, e);//触发button事件  
                }
            }
            #endregion
            /*****************************************************************/
        }
    }
    
    

    四、客户端完整代码

    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    using System.Threading;
    using System.Threading.Tasks;
    using System.Windows.Forms;
    
    namespace Client
    {
        public partial class Form1 : Form
        {
            public static Socket ClientSocket;  //声明负责通信的socket
            public static int SFlag = 0;    //连接服务器成功标志
            Thread th1;     //声明一个线程
    
            public Form1()
            {
                InitializeComponent();
            }
    
            private void Form1_Load(object sender, EventArgs e)
            { 
                Control.CheckForIllegalCrossThreadCalls = false;    //执行新线程时跨线程资源访问检查会提示报错,所以这里关闭检测
            }
    
            /*****************************************************************/
            #region 连接服务器端
            private void button_Connect_Click(object sender, EventArgs e)
            {
                ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);     //声明负责通信的套接字
                
                richTextBox_Recieve.Text += "正在连接...\n";
                
                IPAddress IP = IPAddress.Parse(textBox_Addr.Text);      //获取设置的IP地址
                int Port = int.Parse(textBox_Port.Text);       //获取设置的端口号
                IPEndPoint iPEndPoint = new IPEndPoint(IP,Port);    //指定的端口号和服务器的ip建立一个IPEndPoint对象
    
                try
                {  
                    ClientSocket.Connect(iPEndPoint);       //用socket对象的Connect()方法以上面建立的IPEndPoint对象做为参数,向服务器发出连接请求
                    SFlag = 1;  //若连接成功将标志设置为1
                        
                    richTextBox_Recieve.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + textBox_Addr.Text + "连接成功" + "\n";
                    button_Connect.Enabled = false;     //禁止操作连接按钮
                    
                    //开启一个线程接收数据
                    th1 = new Thread(Receive);
                    th1.IsBackground = true;
                    th1.Start(ClientSocket);    
                }
                catch 
                {
                    MessageBox.Show("服务器未打开");
                }    
            }
            #endregion
            /*****************************************************************/
    
            /*****************************************************************/
            #region 接收服务器端数据
            void Receive(Object sk)
            {
                Socket socketRec = sk as Socket;
    
                while (true)
                {
                    //5.接收数据
                    byte[] receive = new byte[1024];
                    ClientSocket.Receive(receive);  //调用Receive()接收字节数据
    
                    //6.打印接收数据
                    if (receive.Length > 0)
                    {
                        richTextBox_Recieve.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + "接收:";   //打印接收时间
                        richTextBox_Recieve.Text += Encoding.ASCII.GetString(receive);  //将字节数据根据ASCII码转成字符串
                        richTextBox_Recieve.Text += "\r\n";
                    }
                }
            }
            #endregion
            /*****************************************************************/
    
            /*****************************************************************/
            #region 向服务器端发送数据
            private void button_Send_Click(object sender, EventArgs e)
            {
                //只有连接成功了才能发送数据,接收部分因为是连接成功才开启线程,所以不需要使用标志
                if (SFlag == 1)
                {
                    byte[] send = new byte[1024];
                    send = Encoding.ASCII.GetBytes(richTextBox_Send.Text);  //将文本内容转换成字节发送
                    ClientSocket.Send(send);    //调用Send()函数发送数据
    
                    richTextBox_Recieve.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ") + "发送:";   //打印发送数据的时间
                    richTextBox_Recieve.Text += richTextBox_Send.Text + "\n";   //打印发送的数据
                    richTextBox_Send.Clear();   //清空发送框
                }
            }
            #endregion
            /*****************************************************************/
    
            /*****************************************************************/
            #region 关闭客户端
            private void buttonClose_Click(object sender, EventArgs e)
            {
                //保证是在连接状态下退出
                if (SFlag == 1)
                {
                    byte[] send = new byte[1024];
                    send = Encoding.ASCII.GetBytes("*close*");  //关闭客户端时给服务器发送一个退出标志
                    ClientSocket.Send(send);
                    
                    th1.Abort();    //关闭线程
                    ClientSocket.Close();   //关闭套接字
                    button_Connect.Enabled = true;  //允许操作按钮
                    SFlag = 0;  //客户端退出后将连接成功标志程序设置为0
                    richTextBox_Recieve.Text += DateTime.Now.ToString("yy-MM-dd hh:mm:ss  ");
                    richTextBox_Recieve.Text += "客户端已关闭" + "\n";
                    MessageBox.Show("已关闭连接");
                }
            }
            #endregion
            /*****************************************************************/
    
            /*****************************************************************/
            #region 点击enter发送数据
            private void richTextBox_Send_KeyDown(object sender, KeyEventArgs e)
            {
                if (e.KeyCode == Keys.Enter)//如果输入的是回车键  
                {
                    this.button_Send_Click(sender, e);//触发button事件  
                }
            }
            #endregion
            /*****************************************************************/
        }
    }
    
    
    展开全文
  • C# socket编程教程

    2012-05-21 13:33:04
    从书中截取的,想了解C#SOCKET开发的朋友可以参考下
  • 让不懂SuperSOCKET的初学人员可以快速(只花几分钟的功夫)搭建自己的简易服务器和Telnet客户端通信。先从大方向讲解要做哪些基础工作(下载哪些组件,组件该如何配置),然后叙述要编写哪几步逻辑等等,方便初学者...
  • C#Socket的使用

    千次阅读 2021-09-20 20:09:14
    1.什么是Socket 2.Socket通信模型: 第一步:服务端监听某个端口 第二步:客户端向服务端地址和端口发起Socket请求 第三步:服务器接收连接请求后创建Socket连接,并维护这个连接队列 第四步:客户端和服务端就建立起了...

    好记性不如烂笔头

    1.什么是Socket

    2.Socket通信模型:

    第一步:服务端监听某个端口

    第二步:客户端向服务端地址和端口发起Socket请求

    第三步:服务器接收连接请求后创建Socket连接,并维护这个连接队列

    第四步:客户端和服务端就建立起了双工同信,客户端与服务端就可以实现彼此发送消息

    3.服务端代码的实现

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    
    namespace Server
    {
        class Program
        {
            static Socket ReceiveSocket;
    
            static void Main(string[] args)
            {
    
                int port = 8885;
                IPAddress ip = IPAddress.Any;  // 侦听所有网络客户接口的客活动
                ReceiveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//使用指定的地址簇协议、套接字类型和通信协议   <br>            ReceiveSocket.SetSocketOption(SocketOptionLevel.Socket,SocketOptionName.ReuseAddress,true);  //有关套接字设置
                IPEndPoint endPoint = new IPEndPoint(ip, port);
                ReceiveSocket.Bind(new IPEndPoint(ip, port)); //绑定IP地址和端口号
                ReceiveSocket.Listen(10);  //设定最多有10个排队连接请求
                Console.WriteLine("建立连接");
                Socket socket = ReceiveSocket.Accept();
    
                byte[] receive = new byte[1024];
                socket.Receive(receive);
                Console.WriteLine("接收到消息:" + Encoding.ASCII.GetString(receive));
                byte[] send = Encoding.ASCII.GetBytes("Success receive the message,send the back the message");
                socket.Send(send);
                Console.WriteLine("发送消息为:" + Encoding.ASCII.GetString(send));
                Console.ReadLine();
            }
        }
    }
    
    

    4.客户端代码的实现

    using System;
    using System.Net;
    using System.Net.Sockets;
    using System.Text;
    
    namespace Client
    {
        class Program
        {
            // 1:建立一个Socket对像;
            //2:用socket对像的Connect()方法以上面建立的EndPoint对像做为参数,向服务器发出连接请求;
            //3:如果连接成功,就用socket对像的Send()方法向服务器发送信息;
            //4:用socket对像的Receive()方法接受服务器发来的信息 ;
            //5:通信结束后一定记得关闭socket;
            static Socket ClientSocket;
            static void Main(string[] args)
            {
                String IP = "127.0.0.1";
                int port = 8885;
    
                IPAddress ip = IPAddress.Parse(IP);  //将IP地址字符串转换成IPAddress实例
                ClientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//使用指定的地址簇协议、套接字类型和通信协议
                IPEndPoint endPoint = new IPEndPoint(ip, port); // 用指定的ip和端口号初始化IPEndPoint实例
                ClientSocket.Connect(endPoint);  //与远程主机建立连接
    
    
                Console.WriteLine("开始发送消息");
                var a=  Console.ReadLine();
                byte[] message = Encoding.ASCII.GetBytes(a);  //通信时实际发送的是字节数组,所以要将发送消息转换字节
                ClientSocket.Send(message);
                Console.WriteLine("发送消息为:" + Encoding.ASCII.GetString(message));
                byte[] receive = new byte[1024];
                int length = ClientSocket.Receive(receive);  // length 接收字节数组长度
                Console.WriteLine("接收消息为:" + Encoding.ASCII.GetString(receive));
                ClientSocket.Close();  //关闭连接
            }
        }
    }
    
    

    我的公众号

    展开全文
  • C# Socket网络通信基础教程

    万次阅读 多人点赞 2018-08-24 23:13:37
    Socket链接的流程 套接字是支持TCP/IP协议网络通信的基本操作单元可以将套接字看作不同主机间的进程双向通信的端点, 它构成了单个主机内及整个网络间的编程界面。 套接字存在于通信域中, 通信域是为了处理 一般的...

    Socket链接的流程

    套接字是支持TCP/IP协议网络通信的基本操作单元可以将套接字看作不同主机间的进程双向通信的端点, 它构成了单个主机内及整个网络间的编程界面。 套接字存在于通信域中, 通信域是为了处理
    一般的线程通过套接字通信而引进的一种抽象概念。 套接字通常会和同一个域中的套接字交换数据(数据交换也可能会穿越域的界限, 但这时一定要执行某种解释程序) 。 各种进程使用这个相同的域用

    图6-14展示的是一套基本的Socket通信流程。

    Socket通信的基本流程具体步骤如下所示

    1.开启一个链接之前,需要先完成Socket和Bind两个步骤。Socket是新建一个套接字,Bind指定套接字的IP和端口(客户端在调用Connect时会由系统分配端口,因此可以省去Bind)。

    2.服务端通过Listen开启监听,等待客户端接入。

    3.客户端通过Connect连接服务器, 服务端通过Accept接收客户端连接。 在connect-accept过程中, 操作系统将会进行三次握手

    4.客户端和服务端通过write和read发送和接收数据, 操作系统将会完成TCP数据的确认、 重发等步骤。

    5.通过close关闭连接, 操作系统会进行四次挥手。

    Socket类
    System.Net.Sockets命名空间的Socket类为网络通信提供了一套丰富的方法和属性, 表6-6和表6-7列举了Socket类的一些常用方法和属性。

    编写服务端程序
    服务器遵照Socket通信的基本流程, 先创建Socket, 再调用Bind绑定IP地址和端口号, 之后调用Listen等待客户端连接。 最后在while循环中调用Accept接收客户端的连接, 并回应消息。

    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
    using System.Threading.Tasks;
    using System.Net;
    using System.Net.Sockets;

    namespace SocketServerDemo
    {
        class Program
        {
            static void Main(string[] args)
            {
                Console.WriteLine("hello world!");
                //新建一个套接字Socket即创建Socket
                //Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp) ”这一行创建了一个套接字, 它的3个参数分别代表地址族、 套接字类型和协议。 地址族指明是使用IPv4还是IPv6, 含义如表6-8所示, 本例中使用的是IPv4, 即InterNetwork
                Socket listenfd = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
                //Bind指定套接字的IP和端口
                //listenfd.Bind(ipEp) 将给listenfd套接字绑定IP和端口。 示例程序中绑定的是本地地址“127.0.0.1”和1234号端口。 127.0.0.1是回送地址, 指本地机, 一般用于测试。 读者也可以设置成真实的IP地址, 然后在两台电脑上分别运行客户端和服务端程序。
                IPAddress ipAdr = IPAddress.Parse("127.0.0.1");//根据IP地址创建IPAddress对象,如IPAddress.Parse("192.168.1.1")

                IPEndPoint ipEp = new IPEndPoint(ipAdr, 1234);//用IPAddress指定的地址和端口号初始化
                //服务端通过listenfd.Listen(0) 开启监听, 等待客户端连接。 参数backlog指定队列中最多可容纳等待接受的连接数, 0表示不限制
                listenfd.Listen(0);
                Console.WriteLine("[服务器]启动成功");
                while(true)
                {
                    //Accept
                    //开启监听后, 服务器调用listenfd.Accept() 接收客户端连接。 本例使用的所有Socket方法都是阻塞方法, 也就是说当没有客户端连接时, 服务器程序会卡在listenfd.Accept() 处, 而不会往下执行, 直到
                    //接收了客户端的连接。 Accept返回一个新客户端的Socket, 对于服务器来说, 它有一个监听Socket(例子中的listenfd) 用来接收(Accept) 客户端的连接, 对每个客户端来说还有一个专门的Socket(例子中的
                    //connfd) 用来处理该客户端的数据
                    Socket connfd = listenfd.Accept();
                    Console.WriteLine("[服务器]Accept");
                    //Recv
                    //服务器通过connfd.Receive接收客户端数据, Receive也是阻塞方法, 没有收到客户端数据时, 程序将卡在Receive处, 而不会往下执行。 Receive带有一个byte[]类型的参数, 它将存储接收到的数据, Receive
                    //的返回值则指明接收到的数据的长度。 之后使用System.Text.Encoding.UTF8.GetString(readBuff, 0, count) 将byte[] 数组转换成字符串显示在屏幕上。
                    byte[] readBuff = new byte[1024];
                    int count = connfd.Receive(readBuff);
                    string str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
                    Console.WriteLine("[服务器接收]" + str);
                    //Send
                    //服务器通过connfd.Send发送数据, 它接受一个byte[]类型的参数指明要发送的内容。 Send的返回值指明发送数据的长度(例子中没有使用) 。 服务器程序用System.Text.Encoding.Default.GetBytes(字符串)
                    //把字符串转换成byte[] 数组, 然后发送给客户端(且会在字符串前面加上“serv echo”) 
                    byte[] bytes = System.Text.Encoding.Default.GetBytes("serv echo" + str);
                    connfd.Send(bytes);
                   
                }
            }
        }
    }
    客户端程序

    using System.Collections;
    using System.Collections.Generic;
    using UnityEngine;
    using System.Net.Sockets;
    using UnityEngine.UI;

    public class UserNet : MonoBehaviour
    {
        //与服务端的套接字
        Socket socket;
        //服务端的IP和端口
        public InputField hostInput;
        public InputField portInput;
        //文本框
        public Text recvText;
        public Text clientText;
        //接收缓冲区
        const int BUFFER_SIZE = 1024;
        byte[] readBuff = new byte[BUFFER_SIZE];
        public void Connection()
        {
            //Socket
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //Connect
            string host = hostInput.text;
            int port = int.Parse(portInput.text);
            socket.Connect(host, port);
            clientText.text = "客户端地址" + socket.LocalEndPoint.ToString();
            //Send
            string str = "Hello Unity!";
            byte[] bytes = System.Text.Encoding.Default.GetBytes(str);
            socket.Send(bytes);
            //Recv
            int count = socket.Receive(readBuff);
            str = System.Text.Encoding.UTF8.GetString(readBuff, 0, count);
            recvText.text = str;
            //Close
            socket.Close();
        }

        // Use this for initialization
        void Start () {
            
        }
        
        // Update is called once per frame
        void Update () {
            
        }
    }
     

    展开全文
  • 多线程和Socket编程初步教程,非常适合初学者。
  • 让不懂SuperSOCKET的初学人员可以快速(只花几分钟的功夫)搭建自己的简易服务器。先从大方向讲解要做哪些基础工作(下载哪些组件,组件该如何配置),然后叙述要编写哪几步逻辑等等,方便初学者掌握大方向该如何...
  • 主要给大家介绍了关于C#学习教程Socket的简单使用,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面来一起学习学习吧
  • C#Socket教程详解一:同步TCP编程

    千次阅读 2018-07-18 15:06:13
    异步TCP编程传送门:C#Socket教程详解二:异步TCP编程_shazhiwutx的博客-CSDN博客_c# tcp编程 服务端重要类: TcpListener类,服务器监听类,用于监听和连接客户端,该类重要方法如下: 构造方法: public Tcp...
  • 让不懂SuperSOCKET的初学人员可以快速(只花几分钟的功夫)搭建自己的简易服务器。先从大方向讲解要做哪些基础工作(下载哪些组件,组件该如何配置),然后叙述要编写哪几步逻辑等等,方便初学者掌握大方向该如何...
  • 异步TCP编程基本知识: 1.什么是异步TCP编程? 就是在发送或接受消息时,不需要等待,可以先做其他事情,等发送或接受信息完毕之后通过 回调函数执行后面需要进行的操作。...2.异步TCP编程需要掌握的4个方法,一个...
  • C# 完整版 Socket 编程,socket编程详细pdf 教程
  • C#多线程和Socket网络编程精讲 徐照兴,教研室主任,硕士,副教授,专业...
  • C# Socket实战源码

    2020-12-08 11:37:43
    Socket对象的RemoteEndPoint、LocalEndPoint都是这个类型 属性Address:使用IPv4表示的地址 属性Port:使用int表示的端口 类Socket 这个类既可以用于服务器端的开发,也可以用于客户端的开发; 构造方法: 参数...
  • 最近一个项目因为要用到Socket传输问题,所以决定学习一下,将自己学习的内容总结分享出来,下面这篇文章主要给大家介绍了关于C# .NET中Socket简单实用框架使用的相关资料,文中通过示例代码介绍的非常详细,需要的...
  • C#Socket通信用法实例详解

    千次阅读 2017-11-02 22:22:10
    C#Socket通信用法实例详解_C#教程_脚本之家 http://www.jb51.net/article/72313.htm 这篇文章主要介绍了C#Socket通信用法,以实例形式较为详细的分析了UDP及TCP两种通信方式的具体实现技巧,具有一定参考借鉴价值...
  • 有关Socket原理的文章,网络上可谓是铺天盖地,在这里我就不再赘述,直接上干货。 一、思维导图 先来通过一张脑图,将整体设计结构展现出来。 二、核心文件 整个框架共九个类文件,分别负责独立的业务逻辑。上图中...
  • C#socket调试助手

    2017-09-06 09:13:03
    C#写的实现Socket通讯的小程序。借鉴网上教程写的,可以直接运行调试,零基础的可以借鉴一下,使用多线程来监控消息的接受情况。
  • HP-Socket通讯框架官方教程
  • C#Socket案例

    2021-04-27 14:03:23
    C#使用Socket案例
  • SuperSocket配置section SuperSocket使用.NET自带的配置技术,SuperSocket有一个专门的配置Section: <section name="superSocket" type="SuperSocket.SocketEngine.Configuration.SocketServiceConfig, ...
  • 内容索引:C#源码,网络相关,Socket编程实例 C#.Net程序设计之Socket篇的编程实例,实例是一个...实例运行于VS2008,附有讲解教程,详细讲解一些Socket编程的必要知识以及本实例的实现过程,对C#开发的朋友是个福音。
  • csharp-socket编程使用TCP协议进行基本Socket编程的存储库该存储库基于Hackd Bytes的“教程”系列中的源代码
  • 在SuperSocket 中, 如果你没有定义自己的协议,SuperSocket 将会使用命令行协议, 这会使这样的协议的开发变得很简单。 命令行协议定义了每个请求必须以回车换行结尾 "\r\n"。 如果你在 SuperSocket 中使用...
  • C#高级教程(PPT+源码)
  • 文章目录一、说明二、待测试产品、环境2.1 Socket产品2.2 测试物理机三、测试3.1 服务器测试项目配置3.2 TCP服务器测试参数配置3.3 测试一3.4 测试二3.5 测试三四、综合功能及特性五、最后结语 一、说明 本测试...
  • C#程序挂载为win服务,实现电文收发功能
  • socket服务端 private static Socket serverSocket = null; static void Main(string[] args) { //AddressFamily.InterNetwork 地址族 //SocketType.Stream 指定类型 //ProtocolType.Tcp 指定协议 ...

空空如也

空空如也

1 2 3 4 5 ... 20
收藏数 5,038
精华内容 2,015
关键字:

c#socket教程

c# 订阅
友情链接: cohvenaences.rar