版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/WQFAE01/article/details/78999328
TCP是一种面向连接的,可靠的,基于字节流的传输层通信协议。TCP的工作过程可以分为三个阶段:
一、连接的建立:创建服务器绑定IP跟端口,用于监听客户端发来的连接请求,
客户端向服务器发送连接请求
二、传输数据 :在服务器跟客户端正常连接成功后,可以通过各自的套接字向对方发送数据
三、断开连接:在通信完成后可以通过关闭套接字断开双方的连接,在有一方断开连接后,
另一方就不能再通过该套接字向对方发送数据,必须得重新建立连接
不管在什么系统中,TCP通信方式都是使用的比较多的,这节我们就来学习下在wince系统中是如何实现tcp通信的。
开发系统:wince6.0
开发平台:广州微嵌wince平板
开发工具:visual studio 2008
下面是tcp通信工具的效果图:分为服务器模式跟客户端模式两种
下面是代码详解:
·
using System;
using System.Linq;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.Threading;
namespace Socket_Tcp
{
public partial class Form1 : Form
{
private Socket s_Socket,c_Socket;
private Thread read, accept;
public Form1()
{
//初始化控件
InitializeComponent();
getHostIp();
}
//通过两个CheckBox来选择使用模式:服务器跟客户端
//切换到服务器模式
private void checkBox1_CheckStateChanged(object sender, EventArgs e)
{
this.checkBox2.Checked = false;
this.button3.Text = "打开服务器";
this.disconnect.Text = "关闭服务器";
this.remoteip.ReadOnly = true;
this.remoteport.ReadOnly = true;
this.selfport.Text = "30001";
this.remoteip.Text = "";
this.remoteport.Text = "";
this.remoteip.ReadOnly = true;
this.remoteport.ReadOnly = true;
}
//切换到客户端模式
private void checkBox2_CheckStateChanged(object sender, EventArgs e)
{
this.checkBox1.Checked = false;
this.button3.Text = "连接服务器";
this.disconnect.Text="断开服务器";
this.remoteip.ReadOnly = false;
this.remoteport.ReadOnly = false;
this.selfport.Text = "";
this.remoteport.ReadOnly = false;
this.remoteip.ReadOnly = false;
this.remoteport.Text = "30001";
this.remoteip.Text = "192.168.1.1";
}
//清除接收区
private void button1_Click(object sender, EventArgs e)
{
this.textBox1.Text = "";
}
//打开服务器或连接服务器
private void button3_Click(object sender, EventArgs e)
{
//服务器模式
if (this.checkBox1.Checked)
{
//创建线程用于接收客户端的连接请求
accept = new Thread(AcceptThread);
accept.IsBackground = true;
accept.Start();
}
//客户端模式
else if (this.checkBox2.Checked)
{
//连接服务器
connectToServer();
}
}
//获取本机IP
public void getHostIp()
{
//在c#中获取本地IP的方法
IPHostEntry ipEntry = Dns.GetHostEntry(Dns.GetHostName()); //取得本机IP
string strAddr = ipEntry.AddressList[0].ToString();
this.selfip.Text = strAddr;
}
/*
*在c#中,其它的线程是不能直接更新在主线程中创建的控件,需先声明委托跟委托调用的方法,
*通过委托来在其它线程中更新控件,两者的签名需一致(参数跟返回值类型),
*下面中需要在其它线程中使用到控件均通过该方法实现。
*/
//设置委托用于在线程中获取服务器设置的IP
private delegate int NewDel();
//定义委托调用的方法获取输入框中设置的端口号
private int getPort()
{
this.button3.Enabled = false;
this.button3.Text = "服务器以启动";
this.disconnect.Enabled = true;
this.checkBox1.Enabled = false;
this.checkBox2.Enabled = false;
return Int32.Parse(this.selfport.Text);
}
//设置委托用于在线程中设置远程IP跟端口号
private delegate void GetPoint(string ip, string port);
private void getRemotePoint(string ip, string port)
{
this.disconnect.Enabled = true;
this.button2.Enabled = true;
this.remoteip.Text = (ip.Split(':'))[0];
this.remoteport.Text = (ip.Split(':'))[1];
}
//设置委托用于在线程中显示接收到的数据
private delegate void ReceiveDel(string data);
private void ReceiveData(string data)
{
this.textBox1.Text += data;
}
//服务器用于监听客户端发来的连接请求
private void AcceptThread()
{
//创建服务器socket用于监听客户端的连接,定义一个NewDel的委托,构造参数是调用的方法
//通过Invoke的方法执行该委托方法,Invoke的参数是一个委托
int port = (int)this.Invoke(new NewDel(getPort));
/*创建一个Socket实例,AddressFamily.InterNetwork代表IPV4地址,不包含V6
*SocketType.Stream表示使用的数据流
*ProtocolType.Tcp表示是TCP通信
*/
s_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
try
{
IPHostEntry ip = Dns.GetHostEntry(Dns.GetHostName());
//设置服务器绑定监听的IP地址跟端口号
IPEndPoint point = new IPEndPoint(ip.AddressList[0], port);
s_Socket.Bind(point);
}
catch (SocketException ee)
{
return;
}
//设置最多接收请求连接的数量
s_Socket.Listen(10);
//创建线程等待客户端的连接
while (true)
{
try
{
//该方法会阻塞等待客户端的连接,有客户端发来连接请返回一个Socket的实例用于跟客户端间的通信
c_Socket = s_Socket.Accept();
//获取远程IP跟端口
string c_point = c_Socket.RemoteEndPoint.ToString();
//开启读取线程接收客户端发来的数据
read = new Thread(ReadThread);
read.IsBackground = true;
read.Start();
//利用委托在窗体中显示远程IP跟端口
GetPoint pointdel = new GetPoint(getRemotePoint);
this.Invoke(pointdel,new Object[]{c_point,c_point});
}
catch (Exception e)
{
s_Socket.Close();
break;
}
}
}
//读取线程,用于接收远程机器发来的数据
private void ReadThread()
{
if (c_Socket != null)
{
while (true)
{
byte[] buff = new byte[100];
try
{
//读取远程机器发来的数据
int size = c_Socket.Receive(buff);
if (size > 0)
{
//使用委托显示接受到的数据
ReceiveDel rDel = new ReceiveDel(ReceiveData);
string.Format("from:{0}{1}\r\n",c_Socket.RemoteEndPoint.ToString(),
Encoding.Default.GetString(buff, 0, size))});
}
}catch(Exception e)
{
if (s_Socket != null)
{
s_Socket.Close();
}
break;
}
}
}
}
//发送按键
private void button2_Click(object sender, EventArgs e)
{
if (c_Socket != null)
{
try
{
//通过Socket实例向远程机器发送数据
c_Socket.Send(Encoding.Default.GetBytes(this.textBox2.Text));
}
catch (Exception ee)
{
c_Socket.Close();
if (s_Socket != null)
{
s_Socket.Close();
}
}
}
}
//客户端向服务器发送连接请求
private void connectToServer()
{
c_Socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
//创建一个用于连接服务器的IPEndPoint,参数是服务器监听的IP跟端口号
IPEndPoint point = new IPEndPoint(IPAddress.Parse(this.remoteip.Text),
Int32.Parse(this.remoteport.Text));
try
{
//客户端向服务器发送连接请求
c_Socket.Connect(point);
}
catch (SocketException ee)
{
c_Socket.Close();
return;
}
//判断客户端是否连接上服务器
if (c_Socket.Connected)
{
this.button3.Enabled = false;
this.disconnect.Enabled = true;
this.button2.Enabled = true;
//连接成功开启读取线程接受服务器发来的数据
read = new Thread(ReadThread);
read.IsBackground = true;
read.Start();
//获取本地客户端使用的端口号
string[] str = c_Socket.LocalEndPoint.ToString().Split(':');
this.selfport.Text = str[str.Length - 1];
}
}
//断开连接按键
private void disconnect_Click(object sender, EventArgs e)
{
if (accept != null)
{
//停止服务器接收客户端发送连接请求的线程
accept.Abort();
this.button3.Enabled = true;
this.button3.Text = "打开服务器";
}
//停止读取线程
if (read != null)
{
read.Abort();
}
//关闭服务器
if (s_Socket != null)
{
s_Socket.Close();
}
//关闭服务器或客户端使用的Socket.
if (c_Socket != null)
{
c_Socket.Close();
}
this.disconnect.Enabled = false;
this.button3.Enabled = true;
this.button2.Enabled = false;
this.checkBox1.Enabled = true;
this.checkBox2.Enabled = true;
}
}
}
至此在wince系统上的tcp通信开发的流程就以完成,上面的服务器可以同时跟多个客户端建立连接形成一对多的通信,在服务器的接收线程中可以采用轮询的方式不断地读取各个客户端发来的信息,服务器要想给某一客户端发送信息,选择该客户端相对应得套接字,在通过该套接字给该客户端发送数据即可。