c# 网络编程基础,socket篇[一]

1. 服务端

    用c#创建一个控制台的新项目
    创建方法StartServerSync()实现与客户端的同步服务,但是,这个缺陷很明显,有两个点需要等待
        /// <summary>
        /// 同步式服务器
        /// </summary>
        static void StartServerSync()
        {
            Socket serveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//参数一表示使用ip4,参数二表示使用流传输,参数三表示使用tcp协议
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");//本机ip地址
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 8088);
            serveSocket.Bind(ipEndPoint);//绑定端口号
            serveSocket.Listen(10);//开始监听端口号,10表示一个队列,这个队列最多让十个要进行连接的客户端排队,如果设置为0则可以让无限个要连接的客户端排队让服务端进行处理

            Socket clientSocket = serveSocket.Accept();//使用serveSocket.Accept()使服务器连接一个客户端,此方法会暂停程序直到接收到一个客户端,返回被连接的socket

            //向客户端发送一条信息
            string msg = "welcome !你好";
            byte[] data = Encoding.UTF8.GetBytes(msg);//将字符串转成比特
            clientSocket.Send(data);

            //接受客户端的一条信息
            byte[] dataBuffer = new byte[1024];
            int count = clientSocket.Receive(dataBuffer);//clientSocket.Receive(dataBuffer)接受一条byte数据存入dataBuffer,返回值是接受到的byte的个数,此方法会暂停程序直到接收完数据
            string msgReceive = Encoding.UTF8.GetString(dataBuffer, 0, count);//获取dataBuffer[0]至dataBuffer[count]的byte转化为字符串返回

            Console.WriteLine(msgReceive);
            Console.ReadKey();
            clientSocket.Close();//关闭跟客户端的连接
            serveSocket.Close();//关闭服务端的连接
        }
    接下来实现服务端与客户端的异步连接,可实现多个客户端连接服务端,这里我们用Socket.BeginAccept(AsyncCallback,Object)方法使服务器开始连接一个客户端,其参数AsyncCallback可以是我们自己定义的一个方法,这里我们用自己写的AcceptCallBack(IAsyncResult)方法,第二个参数就是为了给我们的方法传递参数的.
    先定义一个全局变量
        static byte[] dataBuffer = new byte[1024];//用来存储传 收的数据
        /// <summary>
        /// 服务器(异步)
        /// </summary>
        static void StartServerAsync()
        {
            Socket serveSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//参数一表示使用ip4,参数二表示使用流传输,参数三表示使用tcp协议
            IPAddress ipAddress = IPAddress.Parse("127.0.0.1");//本机ip地址
            IPEndPoint ipEndPoint = new IPEndPoint(ipAddress, 8088);
            serveSocket.Bind(ipEndPoint);//绑定端口号
            serveSocket.Listen(10);//开始监听端口号,10表示一个队列,这个队列最多让十个要进行连接的客户端排队,如果设置为0则可以让无限个要连接的客户端排队让服务端进行处理

            serveSocket.BeginAccept(AcceptCallBack, serveSocket);//调用函数AcceptCallBack()开始异步连接客户端
        }
serveSocket.BeginAccept(AcceptCallBack, serveSocket);第二个参数其实就是传递给AcceptCallBack()方法的,相当于AcceptCallBack(serveSocket);
当我们使用serveSocket.BeginAccept(AcceptCallBack, serveSocket)时程序是不会暂停的,会继续执行下去,只是我们在这里并没有需要执行的代码.这只是开始接收一个客户端,并没有接受一个客户端.
我们把服务器socket传递过去方便在方法中实现与客户端的连接
        /// <summary>
        /// 连接客户端的回调函数
        /// </summary>
        /// <param name="ar"></param>
        static void AcceptCallBack(IAsyncResult ar)
        {
            Socket serveSocket = ar.AsyncState as Socket;
            Socket clientSocket = serveSocket.EndAccept(ar);//完成一个客户端的连接

            //向客户端发送一条信息
            string msg = "welcome !你好";
            byte[] data = Encoding.UTF8.GetBytes(msg);//将字符串转成比特
            clientSocket.Send(data);

            //开始监听客户端数据传递//开始接收数据,第四个参数SocketFlags这里不需要,所以.none,ReceiveCallBack()是一个自定义的方法,这里表示我们接收完数据后调用该方法,最后一个参数就是ReceiveCallBack()方法中的参数的传递,这个参数是object类型
            clientSocket.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, clientSocket);

            serveSocket.BeginAccept(AcceptCallBack, serveSocket);//继续处理下一个客户端连接
        }
Socket clientSocket = serveSocket.EndAccept(ar);到这里才是完成了一个客户端socket的连接.
函数的最后从新回调,实现多个客户端的连接.
同样的,我们使用clientSocket.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, clientSocket);开始接受客户端发过来的数据,存到dataBuffer,并切调用ReceiveCallBack()函数,此函数也是个回掉函数,以此来实现每个客户端的多次数据发送.
使用clientScoket.EndReceive(ar)完成客户端数据的传递,此时数据已经存到dataBuffer里,如果客户端非正常关闭,此行代码会出异常,因为clientSocket会为空.如果客户端使用close()方法正常关闭,那么服务器会接受到很多条空数据,以此可以区分客户端关闭方式以便做不同处理.
        /// <summary>
        /// 接收数据的回调函数
        /// </summary>
        /// <param name="ar"></param>
        static void ReceiveCallBack(IAsyncResult ar)
        {
            Socket clientScoket = ar.AsyncState as Socket;//将参数强制转换为socket
            try
            {
                int count = clientScoket.EndReceive(ar);//完成客户端数据的传递,返回比特个数
                //客户端正常关闭服务器就会接受到空数据,但是不会报错,所以这里处理正常关闭的情况
                if(count==0)
                {
                    clientScoket.Close();
                    return;
                }
                string msg = Encoding.UTF8.GetString(dataBuffer, 0, count);
                Console.WriteLine("客户说:" + msg);
                //函数回调,这样就能接收多条数据
                clientScoket.BeginReceive(dataBuffer, 0, 1024, SocketFlags.None, ReceiveCallBack, clientScoket);
            }
            catch (Exception e)
            {
                Console.WriteLine(e);
                //处理非正常关闭的情况
                if(clientScoket==null)
                {
                    clientScoket.Close();
                }
            }
        }

2. 客户端

相比之下客户端代码就相当容易了

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

using System.Net.Sockets;
using System.Net;
namespace FirstSocketClient
{
    class Program
    {
        static void Main(string[] args)
        {
            Socket clientSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            clientSocket.Connect(new IPEndPoint(IPAddress.Parse("127.0.0.1"), 8088));//连接服务端

            //接受信息
            byte[] data =new byte[1024];
            int count = clientSocket.Receive(data);
            string msg = Encoding.UTF8.GetString(data);
            Console.WriteLine(msg);

            //向服务端发送信息
            while (true)
            {
                string s = Console.ReadLine();
                if (s.Equals("//c"))
                {
                    clientSocket.Close();return;
                }
                clientSocket.Send(Encoding.UTF8.GetBytes(s));
            }
        }
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值