C#下使用Socket通信

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/xiaomifanhxx/article/details/80904360

    在说到Socket的TCP通信之前,先给大家讲述整个网络流程:TCP/IP协议分层:网络接口层、网络层、传输层、应用层,而Socket进行通信是应用层与传输层进行通信。

    而应用层向传输层进行信息传递通信的时候,TCP会遇多个客户端同时向一个服务端发出请求,并且该请求信息均通过一个端口来进行传输。为了区别不同的客户端,计算机应用程序与TCP/IP协议交互提供了Socket(套接字)的接口,每一个套接字对应于一组IP+PORT,这样我们就能区分不同的客户端了。

1.Socket的通讯原理

    服务端:

    (1)建立服务器端的Socket即(ServerSocket)

    (2)确定服务器端的IP以及传输端口,并将IP以及ServerSocket进行实例化,通过.bind进行绑定IP以及端口

    (3)然后创建一个线程,服务器端开始监听客户端的信息。

    (4)当有一个客户端进行连接时,创建一个与客户端进行连接通信的Socket,即ClientSocket,通过ServerSocket返回的是该连接的ClientSocket的IP以及端口。

    (5)将上一步连接的Client的Socket进行保存。

    (6)接收到客户端的信息以及给客户端发送信息比较类似。

    代码如下:

    前2步操作,创建ServerSocket,并进行绑定。

//申请一个socket用来监听
int port = 50000;//确定一个端口
string ipofserver = "192.168.0.5";//确定一个IP地址
IPAddress serverip = IPAddress.Parse(ipofserver);//将IP地址字符串转换为IPAddress实例
ServerSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//使用指定的地址簇协议、套接字类型和通信协议
IPEndPoint endPoint = new IPEndPoint(serverip, port);//用指定的ip和端口号初始化IPendPint实例,将服务器端绑定到一个地址和一个端口上
//建立通信
ServerSocket.Bind(endPoint);//绑定IP地址以及端口号
ServerSocket.Listen(10);//设定可以监听10个

       第三步操作,创建线程,进行实时监听。

    

                    Thread client_listen = new Thread(listen_client);//启动线程开始监听
                    client_listen.IsBackground = true;
                    client_listen.Start();

    第4、5步操作,监听到客户端,并将该客户端信息进行保存。

while(true)
            {
                Socket socket_watch = ServerSocket.Accept();//socket.accept保存了给Server发送信息的客户端的ip+port
                this.Invoke(new Action(() =>
                {
                    //向下拉框中添加一个客户端的ip端口字符串,作为客户的唯一标识
                    client_ips.Items.Add(socket_watch.RemoteEndPoint.ToString().Substring(0, socket_watch.RemoteEndPoint.ToString().IndexOf(":")));
                }
                ));
                //将与客户端通信的套接字对象socket_watch添加到键值对集合中,并以客户端IP端口作为键
                dictSocket.Add(socket_watch.RemoteEndPoint.ToString().Substring(0, socket_watch.RemoteEndPoint.ToString().IndexOf(":")), socket_watch);

第6步操作,即ServerSocket接收到ClientSocket的信息,以及给ClientSocket发送信息

在确定了ClientSocket后,监听其对ServerSocket发送的消息,即开启一个线程,来实现服务器接收消息功能。

 try
                {
                    ParameterizedThreadStart pts = new ParameterizedThreadStart(recmessge);//开启一个带有参数传递的线程,传递的参数为.start(参数)
                    Thread trd = new Thread(pts);
                    trd.IsBackground = true;
                    trd.Start(socket_watch);
                    dictThread.Add(socket_watch.RemoteEndPoint.ToString(), trd);
                    this.Invoke((MethodInvoker)delegate
                    {
                        server_receive.AppendText("Client"+socket_watch.RemoteEndPoint.ToString() + "已经上线");
                    });
                }
                catch
                {
                    MessageBox.Show("1234", "", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                }

下面是recmessage代码,读取receive的信息。

Socket socketRec=socketClientpara as Socket;//as作为强制转换
            while(true)
            {
                
                byte[] arr_recmessage = new byte[1024 * 1024];

                int length = -1;
                try
                {
                    length = socketRec.Receive(arr_recmessage);//字节长度
                }
                catch(SocketException ex)
                {

                }
                catch(Exception ex)
                {

                }
                string str = Encoding.UTF8.GetString(arr_recmessage, 0, length);
                this.Invoke(new Action(() =>
                {
                    //向下拉框中添加一个客户端的ip端口字符串,作为客户的唯一标识
                    server_receive.AppendText(client_ips.Text + ":\r\n" + str);//显示IP与信息
                }
                ));

                Thread.Sleep(10);
            }

同理给Client发送消息也是类似代码

byte[] strSendMsg = Encoding.UTF8.GetBytes(sendMsg);
                string strClientKey = client_ips.Text;//通过Key匹配对应ip地址的客户端

                dictSocket[strClientKey].Send(strSendMsg);

                this.Invoke(new Action(() =>
                {
                    server_receive.AppendText("服务器:" + "\r\n" + sendMsg + "\r\n");

                }));
                send_msg.Text = null;

客户端

相对服务端,客户端的操作比较简单:(1)创建一个ClientSocket(2)建立Client与Server的联系(3)接收服务端消息以及发送消息

创建一个ClientSocket的流程与创建一个ServerSocket流程类似,只需要对服务端建立连接即可。代码如下:

                    int port = 50000;
                    string ip = "192.168.0.5";//服务器IP
                    IPAddress serverip = IPAddress.Parse(ip);//将IP地址字符串转换为IPAddress实例
                    Client_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);//使用指定的地址簇协议、套接字类型和通信协议
                    IPEndPoint endPoint = new IPEndPoint(serverip, port);//用指定的ip和端口号初始化IPendPint实例
                    Client_Socket.Connect(endPoint);

然后接收服务端的消息,通过建立一个线程,来不断地接收服务端的信息。

                    Thread servert_listen = new Thread(RecMsg);//启动线程开始监听
                    servert_listen.IsBackground = true;
                    servert_listen.Start();

接收的消息:

                    byte[] arrRecMsg = new byte[1024 * 1024];
                    int length = Client_Socket.Receive(arrRecMsg);
                    string str = Encoding.UTF8.GetString(arrRecMsg, 0, length);
                    this.Invoke(new Action(() =>
                    {
                        receive_info.AppendText("服务器:" + "\r\n" + str + "\r\n");
                    }));

同理发送消息只需要将Receive更改为send即可

 byte[] strSenMsg = Encoding.UTF8.GetBytes(sendMsg);
            Client_Socket.Send(strSenMsg);

            this.Invoke(new Action(() =>
            {
                receive_info.AppendText("客户端:" + "\r\n" + sendMsg + "\r\n");
            }));
            send_msg.Text = null;

2.Socket的通讯方式

    Socket的通讯方式有两种:同步与异步

    同步的工作方式:

    用TCP协议进行编程时,程序执行到发送、接收和监听语句的时候,在未完成工作前,不再继续往下执行,即处于堵塞状态,直到该语句执行结束后,才会继续执行下一句。

    异步的工作方式:

    程序执行到发送、接收和监听语句的时候,不论工作是否完成,继续执行下一句。

3.通讯方式

        在与服务端建立连接后,我们就可以通过此连接来发送和接收数据。端口与端口之间以流(Stream)的形式传输数据,因为几乎任何对象都可以保存在流中,所以可以在客户端与服务端之间传输任何类型的数据。对客户端来说,往流中写入数据,即为想服务器传输数据,从流中读取数据,即为从服务端接收数据。对于服务端也一样。

参考博客:

https://www.cnblogs.com/jamesping/articles/2071932.html

https://www.cnblogs.com/wangfx91/p/3997668.html

https://blog.csdn.net/u011602967/article/details/50728443/

https://blog.csdn.net/buctyyzyn/article/details/78704303



    

    


猜你喜欢

转载自blog.csdn.net/xiaomifanhxx/article/details/80904360
今日推荐