客户端与服务器之间的通信(C#网络编程)

本文详细介绍了如何使用C#进行TCP/IP网络编程,包括TCP/IP模型、端口概念、套接字的使用,以及客户端和服务器的代码实现。通过示例代码展示了客户端如何连接服务器,发送和接收数据,同时提供了服务器端监听和响应客户端的代码。文章还包含了测试代码以验证通信功能,并展示了实际运行效果。
摘要由CSDN通过智能技术生成


前言

本文将讲解如何用C#进行网络编程,如何进行客户端与服务器之间的通信,看完本文你将学会最基本的客户端与服务器之间的通信


一、TCP/IP模型

TCP/IP并非指TCP和IP两种协议,而是指一系列网络通信的协议簇,模型有5层和7层两种,7层模型多添加了表示层和会话层,下面展示5层网络模型,如下所示:
5层网络模型

二、端口(port)

端口的范围为0~65535,可分为3大类,公认服务,注册服务,动态或私有端口,一般来说一个服务对应一个端口,我们通过IP地址找到对应的主机,之后再通过对应的端口找到对应的服务器并与之进行通信.


三、套接字(Socket)

套接字主要分为两种,分别是流式套接字(面向连接,TCP)和数据报套接字(无连接,UDP).服务端的套接字至少有2个,一个负责接收客户端的连接(不负责与客户端进行通信),当检测到客户端的连接时,便通过线程产生一个新的更为复杂的套接字与客户端进行通信,如下所示:
服务器Socket


四、客户端套接字(Socket)

在进行连接服务器时必须指定服务器的地址(确定主机)和端口(确定主机上的服务),如下图所示
客户端与服务器通信


五、C#网络编程

Socket构造函数 public Socket(AddressFamily,SocketType,protocolType)
AddressFamily:指定socket用来解析地址的寻址方案,如指定用IPV4版本连接(InterNetWork),
SocketType:定义打开Socket的类型,
ProtocolType:指定协议,如使用TCP或UPD等

IPAddress:包含一个IP地址,可用以将一个字符串的IP地址进行转化
IPEndPoint:包含IP地址以及端口(IP and port)

对于服务器的Socket来说,我们必须绑定其IP地址以及端口


六、客户端与服务器代码编写(客户端与服务器需在不同的工程中)

1.客户端代码

代码如下(示例):

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Net;
using System.Net.Sockets;
namespace Client
{
    class Client
    {
        private static byte[] result = new byte[1024];
        private Socket clientSocket;

        //表示是否连上服务器
        public bool isConnect = false;
        public Client()
        {
            clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);

        }

        /// <summary>
        /// 连接指定IP地址和端口的服务器
        /// </summary>
        /// <param name="ip">服务器IP地址</param>
        /// <param name="port">服务器端口名称</param>
        public void ConnectServer(string ipStr, int port)
        {
            IPAddress ip = IPAddress.Parse(ipStr);
            IPEndPoint ip_end_point = new IPEndPoint(ip, port);

            try
            {
                clientSocket.Connect(ip_end_point);
                isConnect = true;
                Console.WriteLine("服务器连接成功.....");
            }
            catch
            {
                isConnect = false;
                Console.WriteLine("服务器连接失败.....");
                return;
            }
            //接收服务器发送的数据
            int receiveLength = clientSocket.Receive(result);
            Console.WriteLine( Encoding.UTF8.GetString(result));
        }

        /// <summary>
        /// 发送数据给服务器
        /// </summary>
        /// <param name="data">向服务器发送的数据</param>
        public void SendMessage(string data)
        {
            if (isConnect)
            {
                try
                {
                    clientSocket.Send(Encoding.UTF8.GetBytes(data));
                }
                catch
                {
                    isConnect = false;
                    clientSocket.Shutdown(SocketShutdown.Both);
                    clientSocket.Close();
                }


            }
        }
    }
}

2.服务器代码

代码如下(示例):

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

//引入所需的命名空间
using System.Net;
using System.Net.Sockets;
using System.Threading;

namespace SocketTest
{
    class Server
    {

        private static byte[] result = new byte[1024];
        //服务器端口
        private const int port = 8088;
        //ip地址字符串,127.0.0.1为本机
        private static string ipStr = "127.0.0.1";
        private static Socket serverSocket;
        static void Main(string[] args)
        {
            //字符串IP地址转化成IP地址
            IPAddress ip = IPAddress.Parse(ipStr);
            IPEndPoint ip_end_point = new IPEndPoint(ip, port);

            //创建服务器Socket对象,并设置相关属性
            serverSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //为套接字绑定IP和端口
            serverSocket.Bind(ip_end_point);
            //设置最大长度连接请求队列
            serverSocket.Listen(10);
            //Console.WriteLine("启动监听成功{0}", serverSocket.LocalEndPoint.ToString());
            Thread thread = new Thread(ClientConnectListen);
            thread.Start();
            Console.WriteLine();
        }
        /// <summary>
        /// 客户端连接请求监听
        /// </summary>
        private static void ClientConnectListen()
        {
            while (true)
            {
                Console.WriteLine("服务器启动中.......");
                //为新的客户端连接创建一个Socket对象
                Socket clientSocket = serverSocket.Accept();
                Console.WriteLine("客户端{0}成功连接", clientSocket.RemoteEndPoint.ToString());

                //向连接的客户端送连接成功的数据
                clientSocket.Send(System.Text.Encoding.UTF8.GetBytes("服务器:hello"));

                //为每个客户端连接创建一个线程来接收客户端发来的消息
                Thread thrend = new Thread(ReceiveMessage);
                thrend.Start(clientSocket);


            }
        }

        /// <summary>
        /// 接收指定客户端的消息
        /// </summary>
        /// <param name="clientSocket"></param>
        private static void ReceiveMessage(object clientSocket)
        {
            //return null;
            Socket mClientSocket = (Socket)clientSocket;
            while (true)
            {
                int receiveNumber = mClientSocket.Receive(result);
                //Console.WriteLine("客户端接收{0}消息,长度为{1}", mClientSocket.RemoteEndPoint.ToString(), receiveNumber);
                Console.WriteLine(Encoding.UTF8.GetString(result));
            }
        }
    }
}

3.测试代码

代码如下(示例):

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

namespace Client
{
    class test
    {
        public static void Main(string[] args)
        {
            Client client = new Client();
            client.ConnectServer("127.0.0.1", 8088);
            client.SendMessage("客户端:hello!");
            while (true)
            {

            }
        }
    }
}

该处使用的url网络请求的数据。


七 、实现效果展示

服务器启动:
在这里插入图片描述
启动测试:
在这里插入图片描述

网络编程其实并不高深,无非就是客户端与服务器之间的简单通信而已,当您深入理解其中的原理时,一切都是简单的,当然这里我们只是进行简单的运用.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值