因为手里有好几个东西要做,每天只能抽出一部分时间来弄同一个,所以昨天我看了一下得到本机IP,就被迫去干别的了,今天来实现把这个IP发送到服务端。
实现这个事,一个是同步,一个是异步,各有各的特点吧,今天先说一下如何同步实现
先来看运行结果,点击按钮,将IP发送给老师,报告学生上线:
1、新建项目Student,用来做发送端,代码如下:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Windows.Forms;
namespace Student
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void Form1_Load(object sender, EventArgs e)
{
//得到本机IP
textBox1.Text = GetMyIP();
}
private void button1_Click(object sender, EventArgs e)
{
string IPstr = textBox1.Text;
TcpClient c = new TcpClient();
//建立连接,IP与端口,端口只要没有其它软件占用就可以
c.Connect(IPAddress.Parse("127.0.0.1"), 7878);
if (c.Connected)
{
byte[] bytes = Encoding.UTF8.GetBytes(IPstr);
NetworkStream s = c.GetStream();
s.Write(bytes, 0, bytes.Length);
s.Close();
c.Close();
}
else
{
MessageBox.Show("与目标机器连接失败!");
}
}
///
/// 得到本机IP
///
///
public string GetMyIP()
{
try
{
string computername = Dns.GetHostName();
IPHostEntry ipall = Dns.GetHostEntry(computername);
for (int i = 0; i < ipall.AddressList.Length; i++)
{
string theip = ipall.AddressList[i].ToString();
if (theip.LastIndexOf(".") != -1)
{
return theip;
}
}
return "未得到IP地址";
}
catch (Exception ErrMsg)
{
return ErrMsg.ToString();
}
}
}
}
2、新建一个Teacher项目,用来做接收端,界面就放一个Label1就好,代码如下:
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Windows.Forms;
namespace Teacher
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
//线程
Thread getclientinfo = null;
//TPC连接对像
TcpListener TheClient = null;
private void Form1_Load(object sender, EventArgs e)
{
//此操作需要要线程中进行
getclientinfo = new Thread(new ThreadStart(getclient));
getclientinfo.Start();
}
//得客发送端消息的方法
private void getclient()
{
TheClient = new TcpListener(new IPEndPoint(IPAddress.Any, 7878));
try
{
TheClient.Start();
while (true)
{
try
{
TcpClient client = TheClient.AcceptTcpClient();
//尝试获取数据流
NetworkStream stream = client.GetStream();
if (stream.CanRead)
{
string ipStr = "";
byte[] bytes = new byte[1024];
//数据流长度
int i = stream.Read(bytes, 0, bytes.Length);
//读到字符串中
ipStr = Encoding.UTF8.GetString(bytes, 0, i);
//委托更改控件值,因为在线程中,直接更改会报错
this.Invoke(new Action(
() =>
{
label1.Text = ipStr + "同学上线了!";
//加这句是为了调试同步效果,我暂时注释掉
MessageBox.Show(ipStr);
}));
}
client.Close();
}
//这里可以根据错误原因自己判断
//当关闭窗体时也会引发,如果是这个原因就什么也不做就行
catch
{
//出错时的操作,否则进程不会退出
TheClient.Stop();
getclientinfo.Abort();
}
}
}
finally
{
TheClient.Stop();
}
}
private void Form1_FormClosed(object sender, FormClosedEventArgs e)
{
//关闭窗时的操作,否则进程不会退出
TheClient.Stop();
getclientinfo.Abort();
}
}
}
3、代码已经结束了。下来说一下同步传输的特点
//MessageBox.Show(ipStr); //可以加一个对话框看下效果
接收端如果加上了这个对话框代码,接收端弹出对话框以后,如果你不关掉它,程序会是阻塞状态,你必须关闭对话框,才能继续。如下图:
总结:需要注意的主要有3点
1、是在线程中更改控件值需要用委托,
this.Invoke(new Action()
如果用action用不太好,可以用delegate,比较简单,如果不更改控件不需要用委托
2、接收端要做关闭线程和连接对象处理,否则关闭窗体后,进程不会退出
3、因为是同步,如果一个true循环没有结束,就会阻塞
明天再来说说异步的处理方式。