TCP通信之Socket
来源:互联网 发布:跳过windows update 编辑:程序博客网 时间:2024/04/29 01:50
一、Socket介绍
程序员可以通过socket来发送和接收网络上的数据。
在C#中,MS为我们提供了 System.Net.Sockets 命名空间,里面包含了Socket类。
二、访问网络
要想访问网络,还得有些基本的条件:
a. 要确定本机的IP和端口,socket只有与某一IP和端口绑定,才能发挥强大的威力。
b. 得有协议吧(否则谁认得你这发送到网络的是什么呀)。TCP & UDP。
如果具备了基本的条件,就可以开始用它们访问网络了。来看看步骤吧:
a. 建立一个套接字,绑定本机的IP和端口
套件字: 就是网络通信的接口,一个IP地址 然后 接上冒号和端口。相当于家门前的邮箱。
c. 如果是TCP,因为是面向连接的,所以要利用ListenO()方法来监听网络上是否有人给自己发东西;如果是UDP,因为是无连接的,所以来者不拒。
d. TCP情况下,如果监听到一个连接,就可以使用accept来接收这个连接,然后就可以利用Send/Receive来执行操作了。而UDP,则不需要accept, 直接使用SendTo/ReceiveFrom来执行操作。(看清楚哦,和TCP的执行方法有区别,因为UDP不需要建立连接,所以在发送前并不知道对方的IP和端口,因此需要指定一个发送的节点才能进行正常的发送和接收)
e. 如果你不想继续发送和接收了,就不要浪费资源了。能close的就close吧。
三、流程图
代码:
/// <summary> /// 设计器支持所需的方法 - 不要 /// 使用代码编辑器修改此方法的内容。 /// </summary> private void InitializeComponent() { this.groupBox1 = new System.Windows.Forms.GroupBox(); this.radioButton2 = new System.Windows.Forms.RadioButton(); this.radioButton1 = new System.Windows.Forms.RadioButton(); this.label1 = new System.Windows.Forms.Label(); this.ServerIP = new System.Windows.Forms.TextBox(); this.label2 = new System.Windows.Forms.Label(); this.ServerPort = new System.Windows.Forms.TextBox(); this.label3 = new System.Windows.Forms.Label(); this.ClientIp = new System.Windows.Forms.ComboBox(); this.BtnStartListener = new System.Windows.Forms.Button(); this.BtnStopListener = new System.Windows.Forms.Button(); this.label4 = new System.Windows.Forms.Label(); this.TextRead = new System.Windows.Forms.TextBox(); this.label5 = new System.Windows.Forms.Label(); this.TextWrite = new System.Windows.Forms.TextBox(); this.CheckBoxRead = new System.Windows.Forms.CheckBox(); this.BtnReadClear = new System.Windows.Forms.Button(); this.CheckBoxWrite = new System.Windows.Forms.CheckBox(); this.BtnWriteClear = new System.Windows.Forms.Button(); this.BtnWrite = new System.Windows.Forms.Button(); this.groupBox1.SuspendLayout(); this.SuspendLayout(); // // groupBox1 // this.groupBox1.Controls.Add(this.radioButton2); this.groupBox1.Controls.Add(this.radioButton1); this.groupBox1.Location = new System.Drawing.Point(12, 12); this.groupBox1.Name = "groupBox1"; this.groupBox1.Size = new System.Drawing.Size(175, 53); this.groupBox1.TabIndex = 0; this.groupBox1.TabStop = false; this.groupBox1.Text = "TCP协议类型"; // // radioButton2 // this.radioButton2.AutoSize = true; this.radioButton2.Location = new System.Drawing.Point(95, 20); this.radioButton2.Name = "radioButton2"; this.radioButton2.Size = new System.Drawing.Size(59, 16); this.radioButton2.TabIndex = 1; this.radioButton2.Text = "客户端"; this.radioButton2.UseVisualStyleBackColor = true; // // radioButton1 // this.radioButton1.AutoSize = true; this.radioButton1.Checked = true; this.radioButton1.Location = new System.Drawing.Point(6, 20); this.radioButton1.Name = "radioButton1"; this.radioButton1.Size = new System.Drawing.Size(59, 16); this.radioButton1.TabIndex = 0; this.radioButton1.TabStop = true; this.radioButton1.Text = "服务端"; this.radioButton1.UseVisualStyleBackColor = true; // // label1 // this.label1.AutoSize = true; this.label1.Location = new System.Drawing.Point(210, 12); this.label1.Name = "label1"; this.label1.Size = new System.Drawing.Size(77, 12); this.label1.TabIndex = 1; this.label1.Text = "服务器地址:"; // // ServerIP // this.ServerIP.Location = new System.Drawing.Point(283, 9); this.ServerIP.Name = "ServerIP"; this.ServerIP.Size = new System.Drawing.Size(142, 21); this.ServerIP.TabIndex = 2; // // label2 // this.label2.AutoSize = true; this.label2.Location = new System.Drawing.Point(441, 12); this.label2.Name = "label2"; this.label2.Size = new System.Drawing.Size(77, 12); this.label2.TabIndex = 3; this.label2.Text = "服务器端口:"; // // ServerPort // this.ServerPort.Location = new System.Drawing.Point(515, 9); this.ServerPort.Name = "ServerPort"; this.ServerPort.Size = new System.Drawing.Size(67, 21); this.ServerPort.TabIndex = 4; this.ServerPort.Text = "1234"; // // label3 // this.label3.AutoSize = true; this.label3.Location = new System.Drawing.Point(210, 53); this.label3.Name = "label3"; this.label3.Size = new System.Drawing.Size(65, 12); this.label3.TabIndex = 5; this.label3.Text = "在线客户:"; // // ClientIp // this.ClientIp.FormattingEnabled = true; this.ClientIp.Location = new System.Drawing.Point(281, 50); this.ClientIp.Name = "ClientIp"; this.ClientIp.Size = new System.Drawing.Size(300, 20); this.ClientIp.TabIndex = 6; // // BtnStartListener // this.BtnStartListener.Location = new System.Drawing.Point(618, 3); this.BtnStartListener.Name = "BtnStartListener"; this.BtnStartListener.Size = new System.Drawing.Size(75, 30); this.BtnStartListener.TabIndex = 7; this.BtnStartListener.Text = "开始监听"; this.BtnStartListener.UseVisualStyleBackColor = true; this.BtnStartListener.Click += new System.EventHandler(this.BtnStartListener_Click); // // BtnStopListener // this.BtnStopListener.BackgroundImageLayout = System.Windows.Forms.ImageLayout.None; this.BtnStopListener.Enabled = false; this.BtnStopListener.Location = new System.Drawing.Point(618, 45); this.BtnStopListener.Name = "BtnStopListener"; this.BtnStopListener.Size = new System.Drawing.Size(75, 29); this.BtnStopListener.TabIndex = 8; this.BtnStopListener.Text = "停止监听"; this.BtnStopListener.UseVisualStyleBackColor = true; this.BtnStopListener.Click += new System.EventHandler(this.BtnStopListener_Click); // // label4 // this.label4.AutoSize = true; this.label4.Font = new System.Drawing.Font("宋体", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label4.ForeColor = System.Drawing.Color.DarkRed; this.label4.Location = new System.Drawing.Point(209, 93); this.label4.Name = "label4"; this.label4.Size = new System.Drawing.Size(127, 28); this.label4.TabIndex = 9; this.label4.Text = "接收数据显示窗口\r\n\r\n"; // // TextRead // this.TextRead.Location = new System.Drawing.Point(13, 117); this.TextRead.Multiline = true; this.TextRead.Name = "TextRead"; this.TextRead.Size = new System.Drawing.Size(568, 158); this.TextRead.TabIndex = 10; // // label5 // this.label5.AutoSize = true; this.label5.Font = new System.Drawing.Font("宋体", 10.5F, System.Drawing.FontStyle.Bold, System.Drawing.GraphicsUnit.Point, ((byte)(134))); this.label5.ForeColor = System.Drawing.Color.DarkRed; this.label5.Location = new System.Drawing.Point(209, 300); this.label5.Name = "label5"; this.label5.Size = new System.Drawing.Size(127, 14); this.label5.TabIndex = 11; this.label5.Text = "发送数据显示窗口"; // // TextWrite // this.TextWrite.Location = new System.Drawing.Point(13, 329); this.TextWrite.Multiline = true; this.TextWrite.Name = "TextWrite"; this.TextWrite.Size = new System.Drawing.Size(568, 158); this.TextWrite.TabIndex = 12; // // CheckBoxRead // this.CheckBoxRead.AutoSize = true; this.CheckBoxRead.Location = new System.Drawing.Point(618, 131); this.CheckBoxRead.Name = "CheckBoxRead"; this.CheckBoxRead.Size = new System.Drawing.Size(84, 16); this.CheckBoxRead.TabIndex = 13; this.CheckBoxRead.Text = "16进制格式"; this.CheckBoxRead.UseVisualStyleBackColor = true; // // BtnReadClear // this.BtnReadClear.Location = new System.Drawing.Point(618, 168); this.BtnReadClear.Name = "BtnReadClear"; this.BtnReadClear.Size = new System.Drawing.Size(75, 25); this.BtnReadClear.TabIndex = 14; this.BtnReadClear.Text = "清 空"; this.BtnReadClear.UseVisualStyleBackColor = true; this.BtnReadClear.Click += new System.EventHandler(this.BtnReadClear_Click); // // CheckBoxWrite // this.CheckBoxWrite.AutoSize = true; this.CheckBoxWrite.Location = new System.Drawing.Point(618, 351); this.CheckBoxWrite.Name = "CheckBoxWrite"; this.CheckBoxWrite.Size = new System.Drawing.Size(84, 16); this.CheckBoxWrite.TabIndex = 16; this.CheckBoxWrite.Text = "16进制格式"; this.CheckBoxWrite.UseVisualStyleBackColor = true; // // BtnWriteClear // this.BtnWriteClear.Location = new System.Drawing.Point(618, 383); this.BtnWriteClear.Name = "BtnWriteClear"; this.BtnWriteClear.Size = new System.Drawing.Size(75, 25); this.BtnWriteClear.TabIndex = 17; this.BtnWriteClear.Text = "清 空"; this.BtnWriteClear.UseVisualStyleBackColor = true; this.BtnWriteClear.Click += new System.EventHandler(this.BtnWriteClear_Click); // // BtnWrite // this.BtnWrite.Location = new System.Drawing.Point(618, 427); this.BtnWrite.Name = "BtnWrite"; this.BtnWrite.Size = new System.Drawing.Size(75, 25); this.BtnWrite.TabIndex = 18; this.BtnWrite.Text = "发 送"; this.BtnWrite.UseVisualStyleBackColor = true; this.BtnWrite.Click += new System.EventHandler(this.BtnWrite_Click); // // Form1 // this.AutoScaleDimensions = new System.Drawing.SizeF(6F, 12F); this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font; this.ClientSize = new System.Drawing.Size(701, 499); this.Controls.Add(this.BtnWrite); this.Controls.Add(this.BtnWriteClear); this.Controls.Add(this.CheckBoxWrite); this.Controls.Add(this.BtnReadClear); this.Controls.Add(this.CheckBoxRead); this.Controls.Add(this.TextWrite); this.Controls.Add(this.label5); this.Controls.Add(this.TextRead); this.Controls.Add(this.label4); this.Controls.Add(this.BtnStopListener); this.Controls.Add(this.BtnStartListener); this.Controls.Add(this.ClientIp); this.Controls.Add(this.label3); this.Controls.Add(this.ServerPort); this.Controls.Add(this.label2); this.Controls.Add(this.ServerIP); this.Controls.Add(this.label1); this.Controls.Add(this.groupBox1); this.Name = "Form1"; this.Text = "TCP"; this.FormClosing += new System.Windows.Forms.FormClosingEventHandler(this.Form1_FormClosing); this.groupBox1.ResumeLayout(false); this.groupBox1.PerformLayout(); this.ResumeLayout(false); this.PerformLayout(); } #endregion private System.Windows.Forms.GroupBox groupBox1; private System.Windows.Forms.RadioButton radioButton2; private System.Windows.Forms.RadioButton radioButton1; private System.Windows.Forms.Label label1; private System.Windows.Forms.TextBox ServerIP; private System.Windows.Forms.Label label2; private System.Windows.Forms.TextBox ServerPort; private System.Windows.Forms.Label label3; private System.Windows.Forms.ComboBox ClientIp; private System.Windows.Forms.Button BtnStartListener; private System.Windows.Forms.Button BtnStopListener; private System.Windows.Forms.Label label4; private System.Windows.Forms.TextBox TextRead; private System.Windows.Forms.Label label5; private System.Windows.Forms.TextBox TextWrite; private System.Windows.Forms.CheckBox CheckBoxRead; private System.Windows.Forms.Button BtnReadClear; private System.Windows.Forms.CheckBox CheckBoxWrite; private System.Windows.Forms.Button BtnWriteClear; private System.Windows.Forms.Button BtnWrite;
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 TCPApplication{ public partial class Form1 : Form { /// <summary> /// 套接字(服务器或客户端) /// </summary> Socket newsock; /// <summary> /// 当前线程列表(非主线程) /// </summary> Dictionary<int, Thread> ThreadList = new Dictionary<int, Thread>(); /// <summary> /// Tcp协议类型 /// </summary> string Tcplx = null; /// <summary> /// 解码器(可以用于汉字) /// </summary> Encoding encoding = Encoding.GetEncoding("GB2312"); /// <summary> /// 设置缓冲区 /// </summary> byte[] receiveBytes = new byte[1024]; /// <summary> /// 接收数据的大小 /// </summary> int recCount; /// <summary> /// 接收的数据 /// </summary> string data = null; //private SynchronizationContext _context = null; public Form1() { InitializeComponent(); IPAddress[] IP = Dns.GetHostAddresses(Dns.GetHostName()); ServerIP.Text = IP[1].ToString(); } private void BtnStartListener_Click(object sender, EventArgs e) { foreach (Control c in groupBox1.Controls) { if ((c is RadioButton) && (c as RadioButton).Checked) { Tcplx = c.Text; } } if (Tcplx == "服务端") { BtnStartListener.Enabled = false; BtnStopListener.Enabled = true; //第1步:建立套接字,返回套接字 newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); //第2步:将套接字与网络端点相连 IPEndPoint ipep = new IPEndPoint(IPAddress.Parse(ServerIP.Text), int.Parse(ServerPort.Text)); //网络端点(IP 地址和端口号) newsock.Bind(ipep);//套接字绑定网络端点 //第3步:并通知TCP,服务器准备接收 newsock.Listen(10);//设置监听最大连接10, //连接线程接收连接 Thread connectThread = new Thread(new ThreadStart(AcceptConnect)); connectThread.Start(); //如果当前线程,不在线程列表中,则加入 if (!ThreadList.ContainsKey(connectThread.ManagedThreadId)) { ThreadList.Add(connectThread.ManagedThreadId, connectThread); } //_context = SynchronizationContext.Current; } if (Tcplx == "客户端") { BtnStartListener.Enabled = false; BtnStopListener.Enabled = true; newsock = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); IPEndPoint ie = new IPEndPoint(IPAddress.Parse(ServerIP.Text), int.Parse(ServerPort.Text));//第1步:客户端套接字 try { //因为客户端只是用来向特定的服务器发送信息,所以不需要绑定本机的IP和端口。不需要监听。 newsock.Connect(ie); } catch (SocketException se) { Console.WriteLine("unable to connect to server"); Console.WriteLine(se.ToString()); return; } Thread receiveThread = new Thread(new ParameterizedThreadStart(ReceiveMessage));//接收线程处理接收的消息 // 启动消息服务线程 receiveThread.Start(newsock); //如果当前线程,不在线程列表中,则加入 if (!ThreadList.ContainsKey(receiveThread.ManagedThreadId)) { ThreadList.Add(receiveThread.ManagedThreadId, receiveThread); } } } /// <summary> /// 接收客户端连接 /// </summary> private void AcceptConnect() { while (true) { try { Console.WriteLine("客户端连接线程:" + Thread.CurrentThread.ManagedThreadId); //第4步:接收连接,等待客户连接 //第5步:当有可用的客户端连接尝试时执行,并返回一个新的socket Socket client = newsock.Accept();//注:每次连接都创建一个客户连接,所以client定义局部的,而不是全局的。Socket是引用类型。 //创建消息服务线程对象,并把连接socket赋于ClientThread //ClientThread newclient = new ClientThread(client); //方法一:当有N个连接客户端的时候,就有N个线程,会对程序性能以及计算机性能影响很大。 //把ClientThread 类的ClientService方法委托给线程 Thread receiveThread = new Thread(new ParameterizedThreadStart(ReceiveMessage));//接收线程处理接收的消息 // 启动消息服务线程 receiveThread.Start(client); //如果当前线程,不在线程列表中,则加入 if (!ThreadList.ContainsKey(receiveThread.ManagedThreadId)) { ThreadList.Add(receiveThread.ManagedThreadId, receiveThread); } //方法二:用线程池的方法对线程进行线程管理(限制最大的线程数,把空闲的线程重新使用,以提高性能) //threadpool的静态方法QueueUserWorkItem(这个方法默认最多能有25个线程) //ThreadPool.QueueUserWorkItem(new WaitCallback(ClientServer)); } catch (Exception ex) { Console.Write("出现异常1:"); Console.WriteLine(ex.ToString()); Console.ReadLine(); } } } //数据处理接口 public void ReceiveMessage(object ClientSocket) { Socket s = (Socket)ClientSocket; try { while (true) { Console.WriteLine("读数据线程:" + Thread.CurrentThread.ManagedThreadId); //第6步:Receive()读数据 recCount = s.Receive(receiveBytes, receiveBytes.Length, 0);//接收信息放到receiveBytes缓冲区 if (recCount != 0)//接收字节数不为空 { data = encoding.GetString(receiveBytes, 0, recCount); //字节解码为字符串 this.Invoke((EventHandler)(delegate { TextRead.Text += data; })); //_context.Post((o) => //{ // TextRead.Text += data; //}, null); //第7步:可读取的字节数为0,Send() 写数据,接收数据成功后给客户端返回OK if (s.Available==0) { if (Tcplx == "服务端") { s.Send(encoding.GetBytes("OK"), 2, 0); } } } else { break; //客户端断开连接,退出读数据循环 } } } catch (Exception ex) { Console.Write("出现异常2:"); Console.WriteLine(ex.ToString()); Console.ReadLine(); } s.Close();//第8步:关闭套接字 } /// <summary> /// 停止监听 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnStopListener_Click(object sender, EventArgs e) { Dictionary<int, Thread>.ValueCollection valueCol = ThreadList.Values; //关闭全部线程 foreach (Thread t in valueCol) { //Thread.Abort()方法来永久销毁一个线程,而且将抛出ThreadAbortException异常。 //并执行s.close 关闭客户连接Socket t.Abort(); } ThreadList.Clear(); //关闭服务器Socket newsock.Close(); //关闭客户连接Socket //如果是传文件的话还需要关闭流文件close BtnStartListener.Enabled = true; BtnStopListener.Enabled = false; } /// <summary> /// 发送信息 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnWrite_Click(object sender, EventArgs e) { newsock.Send(encoding.GetBytes(TextWrite.Text)); } /// <summary> /// 清除接收数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnReadClear_Click(object sender, EventArgs e) { TextRead.Text = ""; } /// <summary> /// 清空发送数据 /// </summary> /// <param name="sender"></param> /// <param name="e"></param> private void BtnWriteClear_Click(object sender, EventArgs e) { TextWrite.Text = ""; } private void Form1_FormClosing(object sender, FormClosingEventArgs e) { //if (DialogResult.OK == MessageBox.Show("你确定要关闭应用程序吗?", "关闭提示", MessageBoxButtons.OKCancel, MessageBoxIcon.Question)) //{ // this.FormClosing -= new FormClosingEventHandler(this.Form1_FormClosing);//为保证Application.Exit();时不再弹出提示,所以将FormClosing事件取消 // Application.Exit();//退出整个应用程序 //} //else //{ // e.Cancel = true; //取消关闭事件 //} Dictionary<int, Thread>.ValueCollection valueCol = ThreadList.Values; //关闭全部线程 foreach (Thread t in valueCol) { //Thread.Abort()方法来永久销毁一个线程,而且将抛出ThreadAbortException异常。 //并执行s.close 关闭客户连接Socket t.Abort(); } ThreadList.Clear(); //关闭服务器Socket newsock.Close(); //关闭客户连接Socket //如果是传文件的话还需要关闭流文件close BtnStartListener.Enabled = true; BtnStopListener.Enabled = false; } }}
参考地址:http://www.cnblogs.com/stg609/archive/2008/11/15/1333889.html
0 0
- TCP通信之Socket
- Socket之TCP通信
- Tcp/Ip Socket通信一之初识
- socket通信之 tcp协议1
- Socket 之 TCP 协议通信-c#实现
- Socket之TCP和UDP协议通信
- Socket通信学习实例一之TCP通信
- 【通信方式五】socket编程之TCP通信
- tcp ip 通信socket
- socket网络通信(tcp)
- socket TCP通信实例
- socket网络通信(tcp)
- <>socket-通信-tcp协议
- Linux Socket TCP通信
- TCP Socket通信学习
- tcp ip 通信socket
- linux TCP socket 通信
- C++ TCP socket通信
- change attached source找不到
- 疯狂Android讲义(第二版)pdf及源码、工具下载
- Java密钥库(KeyStore)
- iOS AutoLayout(2)
- 学习代理 笔记 delegate
- TCP通信之Socket
- Android将logcat输出到屏幕、文件。TextView自动向下滚动、显示最后一行
- linux的制作自解压缩包,并运行程序
- 学习笔记(四)图的遍历
- 使用MediaPlayer和SurfaceView播放视频
- cloudstack源码部署时提示程序包com.sun.image.codec.jpeg不存在
- iOS AutoLayout(3)
- C编译器剖析_5.4.2 中间代码生成及优化_基本块的合并
- 详解原生JavaScript实现div拖拽功能