.NET 中Socket通信示例

以下示例程序实现简单的 Socket 通信,可以开多个客户端。本机测试通过,未做联机测试。
Server
using System.Net;
using System.Net.Sockets;
using System.Threading;
using System.Collections;
 
namespace MySocketServer1
{
    public partial class Form1 : Form
    {
        private IPAddress serverIP = IPAddress.Parse("127.0.0.1");// 以本机作测试
        private IPEndPoint serverFullAddr;// 完整终端地址
        private Socket sock;
        private System.Timers.Timer myTimer;
        private ArrayList alSock;// 当建立了多个连接时用于保存连接
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void btStart_Click(object sender, EventArgs e)
        {
            serverFullAddr = new IPEndPoint(serverIP, 1000);// 取端口号1000
// 构造Socket对象,套接字类型为“流套接字”, 指定五元组中的协议元
            sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType .Tcp);
/ / 指定五元组中的本地二元,即本地主机地址和端口号
            sock.Bind(serverFullAddr);
// 监听是否有连接传入,指定挂起的连接队列的最大值为20
            sock.Listen(20);
 
            alSock = new ArrayList();
 
// 构造定时器,时间间隙为1秒,即每隔一秒执行一次accept()方法,以获取连接请求队列中//第一个挂起的连接请求
            myTimer =new System.Timers.Timer(1000);
            myTimer.Elapsed +=new System.Timers.ElapsedEventHandler(myTimer_Elapsed);
            myTimer.Enabled = true;
        }
 
        private void myTimer_Elapsed(object sender, System.Timers.ElapsedEventArgs e)
        {
            myTimer.Enabled = false;
// 执行accept(),当挂起队列为空时将阻塞本线程,同时由于上一语句,定时器将停止,直//至有连接传入
            Socket acceptSock = sock.Accept();
// 将accept()产生的Socket对象存入ArrayList
           alSock.Add(acceptSock);
// 构造Threading.Timer对象,这将导致程序另启线程。线程将执行回调函数,该委托限制//函数参数须为object型。Threading.Timer构造器的第二个参数即传入回调函数的参数;第//三个参数指定调用回调函数之前的延时,取0则立即启动;最后一个参数指定调用回调函数//的时间间隔,取0则只执行一次。
            System.Threading.Timer ti = new System.Threading.Timer(new
TimerCallback (ReceiveMsg), acceptSock, 0, 0);
            myTimer.Enabled = true;
        }
 
        private void ReceiveMsg(object obj)
        {
            Socket acceptSock = (Socket)obj;
            try
            {
                while (true)
                {
                    byte[] byteArray = new byte[100];
                    acceptSock.Receive(byteArray);// 接收数据
// 将字节数组转成字符串
                    string strRec = System.Text.Encoding.UTF8.GetString(byteArray);
                    if (this.rtbReceive.InvokeRequired)
                    {
                        this.rtbReceive.Invoke(new EventHandler(this.ChangeRickTextBox), new
object [] { strRec, EventArgs.Empty });
                    }
                }
            }
            catch(Exception ex)
            {
                acceptSock.Close();
                MessageBox.Show("S:Receive Message Error"+ex.Message);
            }
        }
 
        private void ChangeRickTextBox(object obj,EventArgs e)
        {
            string s = System.Convert.ToString(obj);
            this.rtbReceive.AppendText(s + Environment.NewLine);
        }
 
        private void btSend_Click(object sender, EventArgs e)
        {
            Socket sc=null;
            byte[] byteSend =
System.Text.Encoding.UTF8.GetBytes(this.tbSend.Text.ToCharArray());
            try
            {
// 同时存在若干个客户端连接时,在textBox1中输入要发送的是哪个连接
                int index = int.Parse(this.textBox1.Text.Trim());
                sc = (Socket)alSock[index - 1];
// 发送数据
                sc.Send(byteSend);
            }
            catch(Exception ex)
            {
if(sc != null)
{
                sc.Close();
}
                MessageBox.Show("S:Send Message Error"+ex.Message);
            }
        }
 
        private void btClose_Click(object sender, EventArgs e)
        {
            try
            {
                Application.Exit();
            }
            catch (Exception ex)
            {
                MessageBox.Show("S:Close Socket Error" + ex.Message);
            }
        }
    }
}
== == == == == == == == == == == == == == == == == == == == == == == == == == == == == == == ==
Client:
using System.Net;
using System.Net.Sockets;
using System.Threading;
 
namespace MySocketClient1
{
    public partial class Form1 : Form
    {
        private IPAddress serverIP = IPAddress.Parse("127.0.0.1");
        private IPEndPoint serverFullAddr;
        private Socket sock;
 
        public Form1()
        {
            InitializeComponent();
        }
 
        private void btConnect_Click(object sender, EventArgs e)
        {
            try
            {
                serverFullAddr = new IPEndPoint(serverIP, 1000);
                sock = new Socket(AddressFamily.InterNetwork, SocketType.Stream,
ProtocolType .Tcp);
                sock.Connect(serverFullAddr);// 建立与远程主机的连接
 
// 启动新线程用于接收数据
                Thread t = new Thread(new ThreadStart(ReceiveMsg));
                t.Name = "Receive Message";
// 一个线程或者是后台线程或者是前台线程。后台线程与前台线程类似,区别是后台线//程不会防止进程终止。一旦属于某一进程的所有前台线程都终止,公共语言运行库就//会通过对任何仍然处于活动状态的后台线程调用 Abort 来结束该进程。
                t.IsBackground = true;
                t.Start();
            }
            catch(Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
 
        private void ReceiveMsg()
        {
            try
            {
                while (true)
                {
                    byte[] byteRec = new byte[100];
                    this.sock.Receive(byteRec);
                    string strRec = System.Text.Encoding.UTF8.GetString(byteRec);
                    if (this.rtbReceive.InvokeRequired)
                    {
                        this.rtbReceive.Invoke(new EventHandler(ChangeRtb), new object[]
{ strRec, EventArgs.Empty });
                    }
                }
            }
            catch(Exception ex)
            {
                MessageBox.Show("Receive Message Error"+ex.Message);
            }
        }
 
        private void ChangeRtb(object obj, EventArgs e)
        {
            string s = System.Convert.ToString(obj);
            this.rtbReceive.AppendText(s + Environment.NewLine);
        }
 
        private void btSend_Click(object sender, EventArgs e)
        {
            byte[] byteSend =
System.Text.Encoding.UTF8.GetBytes(this.tbSend.Text.ToCharArray());
            try
            {
                this.sock.Send(byteSend);
            }
            catch
            {
                MessageBox.Show("Send Message Error");
            }
        }
 
        private void btClose_Click(object sender, EventArgs e)
        {
            try
            {
                this.sock.Shutdown(SocketShutdown.Receive);
                this.sock.Close();
                Application.Exit();
            }
            catch
            {
                MessageBox.Show("Exit Error");
            }
        }
    }
}
不解之处:
Client 端红色标注语句: this.sock.Shutdown(SocketShutdown.Receive) ,如改成
this.sock.Shutdown(SocketShutdown.Both); this.sock.Shutdown(SocketShutdown.Send);
则当点击 Cloce 按钮时, CPU 使用率疯涨到 100% ,而使用 this.sock.Shutdown(SocketShutdown.Receive);
或不调用 Shutdown() 方法则没有这个问题。难道客户端不应该用 Shutdown()
 
  • 0
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 3
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值