Udp打洞简单描述
2009-03-18 08:21:12 来源:WEB开发网和Port,这样2个客户端才算是真正的连通了,这也解释了你的QQ好友隐身问什么你发送消息要等一段时间才能发送成
功的原因所在。当然这是一种比较简单的处理方式,还有一些更复杂点的,技术有限还没去研究过,但这是最基本的原理。
下面是我写的一些示例代码:(聊天没做,不过用户信息都获取到了,做起来很简单了)
客户端,界面自己拖拖就是了,就几个按钮、文本框加个显示所有登陆用户信息的listbox。
Client
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 lib;
using System.Threading;
namespace Client
{
public partial class FrmClient : Form
{
private IPEndPoint hostPoint;//服务器主机地址
private IPEndPoint remotePoint;//目标主机地址
private List<UserInfo> userInfoList;//保存所有登陆用户信息
private Thread listenThread;//监听线程
private UdpClient udpClient;
public FrmClient()
{
InitializeComponent();
userInfoList = new List<UserInfo>();
listenThread = new Thread(new ThreadStart(Run));
}
/**//// <summary>
/// 登陆按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnLogin_Click(object sender, EventArgs e)
{
string serverIp = this.txtIP.Text;
int Port = int.Parse(this.txtPort.Text);
//不需要指定端口,路由会自动跟你的电脑映射一个(除非你要监听一个端口),这里不要错误理解为服务器端口,应该是客户端监听消息的端口
udpClient = new UdpClient();
remotePoint = new IPEndPoint(IPAddress.Any, 0);//提供任何端口和IP,这里不需要指定
hostPoint = new IPEndPoint(IPAddress.Parse(serverIp), Port);//实例化主机地址
LoginServer(this.txtUserName.Text);//由于udpClient还没有连接到服务器,所以要先登陆然后在监听
this.btnLogin.Enabled = false;
listenThread.Start();
}
/**//// <summary>
/// 发送消息按钮事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSend_Click(object sender, EventArgs e)
{
}
/**//// <summary>
/// 登陆服务器
/// </summary>
/// <param name="userName">用户名</param>
private void LoginServer(string userName)
{
UserInfo userInfo = new UserInfo();
userInfo.UserName = userName;
byte[] buffer = SerializeHelper.Serialize(userInfo);
udpClient.Send(buffer, buffer.Length, hostPoint);
buffer = udpClient.Receive(ref remotePoint);
UserList userList = (UserList)SerializeHelper.Deserialize(buffer);
this.userInfoList = userList.userInfoList;
foreach (UserInfo user in userInfoList)
{
this.lstUserInfo.Items.Add(user.UserName + ":" + user.Address.ToString());
}
}
/**//// <summary>
/// 监听线程
/// </summary>
private void Run()
{
byte[] buffer;
while (true)
{
buffer = udpClient.Receive(ref remotePoint);
try
{
object msgObj = SerializeHelper.Deserialize(buffer);
Type msgType = msgObj.GetType();
if (msgType == typeof(UserList))
{
UserList userList = (UserList)msgObj;
this.userInfoList = userList.userInfoList;
this.lstUserInfo.BeginInvoke(new System.EventHandler(ClearUI), this.userInfoList);
}
Thread.Sleep(50);
}
catch
{ }
}
}
/**//// <summary>
/// 获取在线用户列表
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnGetUserInfo_Click(object sender, EventArgs e)
{
GetUserList getUserList = new GetUserList();
byte[] buffer = SerializeHelper.Serialize(getUserList);
udpClient.Send(buffer, buffer.Length, hostPoint);
}
/**//// <summary>
/// 跨线程访问控件
/// </summary>
/// <param name="o"></param>
/// <param name="e"></param>
private void ClearUI(object o, System.EventArgs e)
{
this.lstUserInfo.Items.Clear();
this.lstUserInfo.Items.Add(((UserInfo)o).UserName + ":" + ((UserInfo)o).Address.ToString());
}
/**//// <summary>
/// 窗体关闭事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FrmClient_FormClosed(object sender, FormClosedEventArgs e)
{
try
{
if (this.listenThread.ThreadState == ThreadState.Running)
{
this.listenThread.Abort();
}
udpClient.Close();
}
catch
{ }
}
}
}
更多精彩
赞助商链接