C#之Socket

C#中Socket的简单使用

  1. 服务端监听某个端口
  2. 客户端向服务端地址和端口发起Socket连接请求
  3. 服务端收到连接请求后创建Socket连接,并维护这个连接队列。
  4. 客户端和服务端已经建立双工通信(即双向通信),客户端和服务端可以轻松方便的给彼此发送信息
    图1

    端口

  5. 动态端口 从49152-65535
  6. 机器通常从1024起分配动态端口
  7. 公认端口:0-1023,注册端口: 1024-49151
    ,SUN的RPC端口从 32768开始
  8. 查看端口方式: netstat -a -n

    http协议

    图2
    图3

    Demo

    图4
    图5
    图6

服务端代码:

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;
using System.Net.Sockets;
using System.Threading;

namespace ChatMain
{
    public partial class ChatMain : Form
    {
        public ChatMain()
        {
            InitializeComponent();
            Control.CheckForIllegalCrossThreadCalls = false;
        }
        List<Socket> clientSocketList = new List<Socket>();
        private void btnStart_Click(object sender, EventArgs e)
        {

            string ip = this.txtIP.Text;
            //创建IP
            IPAddress ipAddress = IPAddress.Parse(ip);
            //创建代表本机的节点对象:包含IP和端口
            IPEndPoint endPoint=new IPEndPoint(ipAddress,int.Parse(this.txtPort.Text));
             //创建Socket:第一参数:寻址方式,第二个参数: socket传输方式Stream Tcp方式  Dgram:UDP  第三个参数:协议
            Socket socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            //绑定端口和IP
            socket.Bind(endPoint);
            //开启监听,请求连接的队列的长度
            socket.Listen(10);
            //线程池开启 监听客户端连接
            ThreadPool.QueueUserWorkItem(new WaitCallback(this.statAccept), socket);
            this.txtLog.Text += "服务端开启监听客户端连接了..\r\n";
        }
        public void statAccept(object obj) 
        {
            Socket socket = (Socket)obj;
            try
            {
                while (true)
                {
                    //接受客户端的一个连接
                    Socket proxSocket = socket.Accept();
                    //客户端代理socket对象的队列里面去
                    clientSocketList.Add(proxSocket);
                    //拿到客户端的端口和ip
                    this.txtLog.Text += proxSocket.RemoteEndPoint.ToString() + "\r\n";

                    //跟客户端进行通信 通过:proxSocket

                    //proxSocket.Send()

                    //proxSocket.Receive()
                    ThreadPool.QueueUserWorkItem(new WaitCallback(this.StartReciveClientData), proxSocket);
                }
            }
            catch (Exception  ex)
            {

                socket.Close();
            }
        }
        /// <summary>
        /// 接受连接过来的IP的数据
        /// </summary>
        public void StartReciveClientData(object obj) 
        {
            Socket sokcet = (Socket)obj;
            while (true) 
            {
                byte[] buffer = new byte[1024 * 1024 * 1];
                int  realLenth= sokcet.Receive(buffer,0,buffer.Length,SocketFlags.None);
                string strResult = Encoding.Default.GetString(buffer, 0, realLenth);
                this.txtLog.Text += sokcet.RemoteEndPoint.ToString() + ":" + strResult + "\r\n";
            }
        }

        private void btnStarClient_Click(object sender, EventArgs e)
        {
            ChatClient client = new ChatClient();
            client.Show();
        }

        private void btnSend_Click(object sender, EventArgs e)
        {
            foreach (var socket in clientSocketList)
            {
                string strText = this.txtMsg.Text;
                byte[] data = Encoding.Default.GetBytes(strText);
                socket.Send(data, 0, data.Length, SocketFlags.None);
            }

        }

    }
}

客户端代码:

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 ChatMain
{
    public partial class ChatClient : Form
    {
        public Socket CurrentSocket {get;set; }
        public ChatClient()
        {
            InitializeComponent();
        }

        private void btnConnect_Click(object sender, EventArgs e)
        {

            Socket socket = null;
            IPAddress ipAddress = IPAddress.Parse(this.txtIP.Text);
            IPEndPoint endPoint=new IPEndPoint(ipAddress,int.Parse(this.txtPort.Text));
            //创建个Socket
            socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
            socket.Connect(endPoint);
            ThreadPool.QueueUserWorkItem(new WaitCallback(Recive), socket);
            this.lbStatus.Text = "已连接";
            CurrentSocket = socket;
        }
        //接受
        public void Recive(object obj) {
            Socket socket = (Socket)obj;
            while (socket != null && socket.Connected) 
            {
                byte[] buffer = new byte[1024 * 1024];
                int realLength = socket.Receive(buffer, 0, buffer.Length,SocketFlags.None);
               //接受字符串
                string txt = Encoding.Default.GetString(buffer, 0, realLength);
                this.txtLog.Text += string.Format("接受消息:{0}", txt);
                this.txtLog.Text += "\r\n";

            }
        }
        //发送
        private void btnSend_Click(object sender, EventArgs e)
        {
            string strText = this.txtMsg.Text;
            if (string.IsNullOrEmpty(strText)) {
                this.txtLog.Text = "发送的消息不能为空";

            }
            if (CurrentSocket == null)
            {
                MessageBox.Show("请先连接服务端");
                return;

            }
            byte[] data = Encoding.Default.GetBytes(strText);
            try
            {
                CurrentSocket.Send(data, 0, data.Length, 0);
            }
            catch (Exception)
            {


            }
        }
    }
}


转载请注明: Zhou•Yong C#之Socket

上一篇
截图工具 截图工具
截图工具有段时间公司没网了,写文档要用截图,无法使用心爱的QQ截图了,就自己写了个截图工具,bug有点,没有修复,能用,类似QQ截图,差不多,还蛮好用的,有网以后,就没怎么用了,把代码共享出来 using System; using Sy
2019-01-10
下一篇
SqlServer总结 SqlServer总结
分享一下都是自己写的,总结的,不是照搬网上的,只是分享,其中也有些小案例分享 创建数据库create database schoolA on primary ( name='MyschoolA', filename='D:\databa
2019-01-09
目录