C# TCP/IP网络编程

本文介绍了TCP/IP协议的基础知识及其四层结构,并详细讲解了基于TCP协议的Socket通信原理及其实现过程。通过一个简单的Socket编程示例,展示了服务器与客户端如何建立连接并进行数据交换。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

在开始介绍socket前先补充补充基础知识。
TCP/IP:Transmission Control Protocol/Internet Protocol,传输控制协议/因特网互联协议,又名网络通讯协议。简单来说:TCP控制传输数据,负责发现传输的问题,一旦有问题就发出信号,要求重新传输,直到所有数据安全正确地传输到目的地,而IP是负责给因特网中的每一台电脑定义一个地址,以便传输。从协议分层模型方面来讲:TCP/IP分成网络接口层(链路层)、网络层、传输层、应用层。它和OSI的七层结构以及对于协议族不同,下图简单表示:
TCP/IP的四层结构对应OSI七层结构
图1.TCP/IP的四层结构对应OSI七层结构。
TCP/IP协议族在OSI七层中的位置及对应的功能
图2:TCP/IP协议族在OSI七层中的位置及对应的功能。
TCP/IP协议模块关系图
图3:TCP/IP协议模块关系图。

现阶段socket通信使用TCP、UDP协议,相对应UDP来说,TCP则是比较安全稳定的协议了。本文只涉及到TCP协议来说socket通信。首先讲述TCP/IP的三次握手,在握手基础上延伸socket通信的基本过程。
1.客户端发送syn报文到服务器端,并置发送序号为x。
2.服务器端接收到客户端发送的请求报文,然后向客户端发送syn报文,并且发送确认序号x+1,并置发送序号为y。
3.客户端受到服务器发送确认报文后,发送确认信号y+1,并置发送序号为z。至此客户端和服务器端建立连接。
这里写图片描述
在此基础上,socket连接过程:
服务器监听:服务器端socket并不定位具体的客户端socket,而是处于等待监听状态,实时监控网络状态。
客户端请求:客户端clientSocket发送连接请求,目标是服务器的serverSocket。为此,clientSocket必须知道serverSocket的地址和端口号,进行扫描发出连接请求。
连接确认:当服务器socket监听到或者是受到客户端socket的连接请求时,服务器就响应客户端的请求,建议一个新的socket,把服务器socket发送给客户端,一旦客户端确认连接,则连接建立。
注:在连接确认阶段:服务器socket即使在和一个客户端socket建立连接后,还在处于监听状态,仍然可以接收到其他客户端的连接请求,这也是一对多产生的原因。
下图简单说明连接过程:
这里写图片描述
socket连接原理知道了,此处编写最基本最简单的socket通信(两个程序均为控制台程序):
服务器端:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SocketServer
{
    class Program
    {
        private static byte[] _result = new byte[1024];
        private static int _myPort = 8885;
        static Socket _serverSocket;

        static void Main(string[] args)
        {
            //服务器IP地址
            IPAddress ip = IPAddress.Parse("127.0.0.1");
            _serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            _serverSocket.Bind(new IPEndPoint(ip, _myPort));//绑定IP地址:端口
            _serverSocket.Listen(10);//设定最多10个排队连接请求
            Console.WriteLine("启动监听{0}成功", _serverSocket.LocalEndPoint.ToString());
            //通过Clientsocket发送数据
            Thread myThread = new Thread(ListenClientConnect);
            myThread.Start();
            Console.ReadLine();
        }

        /// <summary>
        /// 监听客户端连接
        /// </summary>
        private static void ListenClientConnect()
        {
            while (true)
            {
                Socket clientSocket = _serverSocket.Accept();
                clientSocket.Send(Encoding.ASCII.GetBytes("Server Say Hello"));
                Thread receiveThread = new Thread(ReceiveMessage);
                receiveThread.Start(clientSocket);
            }
        }

        /// <summary>
        /// 接收消息
        /// </summary>
        /// <param name="clientSocket"></param>
        private static void ReceiveMessage(object clientSocket)
        {
            Socket myClientSocket = (Socket)clientSocket;
            while (true)
            {
                try
                {
                    //通过clientSocket接收数据
                    int receiveNumber = myClientSocket.Receive(_result);
                    Console.WriteLine("接收客户端{0}消息{1}", myClientSocket.RemoteEndPoint.ToString(),
                        Encoding.ASCII.GetString(_result, 0, receiveNumber));
                }
                catch (Exception ex)
                {
                    Console.WriteLine(ex.Message);
                    myClientSocket.Shutdown(SocketShutdown.Both);
                    myClientSocket.Close();
                    break;
                }
            }
        }
    }
}

客户端:

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

namespace SocketClient
{
    class Program
    {
        private static byte[] _result = new byte[1024];

        static void Main(string[] args)
        {
            //设定服务器IP地址
            IPAddress ip = IPAddress.Parse("127.0.0.1");
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            try
            {
                clientSocket.Connect(new IPEndPoint(ip, 8885)); //配置服务器IP与端口
                Console.WriteLine("连接服务器成功");
            }
            catch
            {
                Console.WriteLine("连接服务器失败,请按回车键退出!");
            }
            //通过clientSocket接收数据
            int receiveLength = clientSocket.Receive(_result);
            Console.WriteLine("接收服务器消息:{0}", Encoding.ASCII.GetString(_result, 0, receiveLength));
            //通过clientSocket发送数据
            for (int i = 0; i < 10; i++)
            {
                try
                {
                    Thread.Sleep(1000);//等待1秒钟
                    string sendMessage = "client send Message Hellp" + DateTime.Now;
                    clientSocket.Send(Encoding.ASCII.GetBytes(sendMessage));
                    Console.WriteLine("向服务器发送消息:{0}" + sendMessage);
                }
                catch
                {
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Close();
                    break;
                }
                Console.WriteLine("发送完毕,按回车键退出");
                Console.ReadLine();
            }
        }
    }
}

运行结果:
这里写图片描述
这就完成了一个简单的Socket编程Demo。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值