闲来没事写一个C#的TCP的及时通信,可以在不同的相同机器上运行:全部代码如下
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.Threading;
using System.Net.Sockets;
using System.Diagnostics;
using System.Net;
using System.Text.RegularExpressions;
using System.IO;
using System.Net.NetworkInformation;
using System.Xml.Serialization;
namespace SocketText
{
public partial class FrmText : Form
{
#region Var
public delegate void OperalControl();
private Thread ProcWorkThread = null;
private Thread FlushThread = null;
private bool FlushThreadIsLoop = false;
private int FlushSleepTime = int.MinValue;
private TcpListener ServerListener = null;
private char SplitChar = '^';
private IPAddress MyAddress = null;
private List<string> LocalHostIPList;
private int IPListIndex = 0;
private int LocalHostPort = int.MinValue;
private byte[] CacheBuffer = new byte[1024];
private int CacheBufferLength = 0;
private bool IsloopFlag = false;
private bool ISTrigSendEvent = false;
private System.Windows.Forms.Timer FlushTimer = new System.Windows.Forms.Timer();
private string SaveUserInfoPath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "user.xml");
private int IndexIP = int.MinValue;
private int IndexPort = int.MinValue;
private int IndexIsOnline = int.MinValue;
#endregion
/// <summary>
/// 构造函数
/// </summary>
public FrmText()
{
InitializeComponent();
ColumnHeader IP = new ColumnHeader();
IP.Width = 150;
IP.Name = "IP";
IP.Text = "IP地址";
ColumnHeader Port = new ColumnHeader();
Port.Width = 100;
Port.Name = "Port";
Port.Text = "端口号";
ColumnHeader IsOnline = new ColumnHeader();
IsOnline.Name = "IsOnline";
IsOnline.Text = "是否在线";
IsOnline.Width = 100;
listViewFriend.View = View.Details;
listViewFriend.Columns.AddRange(new ColumnHeader[] { IP, Port, IsOnline });
LocalHostIPList = GetClientIPAddress();
Debug.Assert(LocalHostIPList.Count > 0, "获取本地IP地址失败!");
//获取各个列的索引值 提供给subitems用
IndexIP = listViewFriend.Columns["IP"].Index;
IndexPort = listViewFriend.Columns["Port"].Index;
IndexIsOnline = listViewFriend.Columns["IsOnline"].Index;
}
/// <summary>
/// 窗体加载事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FrmText_Load(object sender, EventArgs e)
{
FlushTimer.Tick += new EventHandler(FlushTimer_Tick);
txtLocalIP.Enabled = false;
IsloopFlag = true;
//读取用户信息
if (File.Exists(SaveUserInfoPath))
{
object userInfo = DeserializeXmL(SaveUserInfoPath, typeof(List<ClientNetINfo>));
List<ClientNetINfo> userInfoList = userInfo as List<ClientNetINfo>;
if (userInfoList != null)
{
LocalHostPort = int.Parse(userInfoList[0].Port);
for (int indx = 1; indx < userInfoList.Count; indx++)
{
ListViewItem item = new ListViewItem(new string[] { userInfoList[indx].IP, userInfoList[indx].Port, "未知" });
item.UseItemStyleForSubItems = false;
item.SubItems[IndexIsOnline].ForeColor = Color.Gray;
item.Name = userInfoList[indx].IP + userInfoList[indx].Port;
listViewFriend.Items.Add(item);
if (!txtFriendIP.Items.Contains(userInfoList[indx].IP))
{
txtFriendIP.Items.Add(userInfoList[indx].IP);
}
}
}
}
ProcWorkThread = new Thread(ListenClient);
ProcWorkThread.IsBackground = true;
ProcWorkThread.Start();
//Thread GetAllIP = new Thread(GetAreaAllIP);
//GetAllIP.IsBackground = true;
//GetAllIP.Start();
}
void GetAreaAllIP()
{
List<string> listIPs = GetLocalAreaOnlineIPs();
OperaControl(txtFriendIP, () => { txtFriendIP.DataSource = listIPs; });
}
/// <summary>
/// 定时器出发事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
void FlushTimer_Tick(object sender, EventArgs e)
{
foreach (ListViewItem item in listViewFriend.Items)
{
bool ret = SendData(InfoEnum.CheckISOnline, "检测是否在线", item.SubItems[IndexIP].Text, item.SubItems[IndexPort].Text);
OperatelistViewFriend(InfoEnum.CheckISOnline, item.SubItems[IndexIP].Text, item.SubItems[IndexPort].Text, ret);
}
}
/// <summary>
/// 监听线程 来监听客户端连接
/// </summary>
private void ListenClient()
{
Socket clientSocket = null;
Random random = new Random();
MyAddress = IPAddress.Parse(LocalHostIPList[IPListIndex]);
while (IsloopFlag)
{
//LocalHostPort = int.Parse(txtLocalPort.Text);
if (LocalHostPort < 0)
{
LocalHostPort = random.Next(0, 65535);
}
try
{
ServerListener = new TcpListener(MyAddress, LocalHostPort);
ServerListener.Start(3);
}
catch (Exception ex)
{
AddlistViewMsg(string.Format("监听IP:{0} 端口:{1}失败!Msg:{2}。", this.MyAddress.ToString(), LocalHostPort.ToString(), ex.Message));
LocalHostPort = random.Next(0, 65535);
continue;
}
OperaControl(txtLocalIP, () => { txtLocalIP.Text = MyAddress.ToString(); });
OperaControl(txtLocalPort, () => { txtLocalPort.Text = LocalHostPort.ToString(); });
AddlistViewMsg(string.Format("监听IP:{0}[{1}]成功。", this.MyAddress.ToString(), LocalHostPort.ToString()));
break;
}
while (IsloopFlag)
{
try
{
clientSocket = ServerListener.AcceptSocket();
//获取得到
//ThreadPool.QueueUserWorkItem(ReciveClient, clientSocket);
clientSocket.ReceiveTimeout = 3000;
CacheBufferLength = clientSocket.Receive(CacheBuffer);
ShowReciveBuffer(Encoding.UTF8.GetString(CacheBuffer, 0, CacheBufferLength));
//完成信息传递后必须断开连接 否则会在成服务端大量客服端连接
clientSocket.Close(5);
}
catch (Exception ex)
{
if (clientSocket != null)
{
clientSocket.Close(5);
}
if (IsloopFlag)
{
AddlistViewMsg("错误异常" + ex.Message);
continue;
}
else
{
break;
}
//ProcWorkThread.Abort();
//throw;
}
}
}
private void ShowReciveBuffer(string recStr)
{
int splitCharNu = recStr.Length - (recStr.Replace(SplitChar.ToString(), "").Length);
if (splitCharNu != 3)
{
AddlistViewMsg(" 收到非法数据: " + recStr);
return;
}
string[] recStrArray = recStr.Split(SplitChar);
InfoEnum infoType = (InfoEnum)(int.Parse(recStrArray[0]));
switch (infoType)
{
case InfoEnum.Unknown:
break;
case InfoEnum.AddFriend:
OperatelistViewFriend(InfoEnum.AddFriend, recStrArray[1].ToString(), recStrArray[2].ToString());
AddlistViewMsg(string.Format(" 添加好友: {0}[{1}] ", recStrArray[1], recStrArray[2]));
break;
case InfoEnum.CheckISOnline:
OperatelistViewFriend(InfoEnum.CheckISOnline, recStrArray[1].ToString(), recStrArray[2].ToString());
//AddlistViewMsg(string.Format(" 上线了{0}:{1} (* ̄︶ ̄)", recStrArray[1], recStrArray[2]));
break;
case InfoEnum.Messages:
AddlistViewMsg(string.Format(" 接收到{0}[{1}]的信息: {2}", recStrArray[1], recStrArray[2], recStrArray[3]));
break;
case InfoEnum.DeleteFriend:
OperatelistViewFriend(InfoEnum.DeleteFriend, recStrArray[1].ToString(), recStrArray[2].ToString());
AddlistViewMsg(string.Format(" 删除了好友: {0}[{1}] ", recStrArray[1], recStrArray[2]));
break;
default:
break;
}
}
/// <summary>
/// 客户端不停接收数据 此链接无需维护
/// </summary>
/// <param name="cliSocket"></param>
void ReciveClient(object cliSocket)
{
Socket client = cliSocket as Socket;
if (client != null)
{
while (IsloopFlag)
{
try
{
EndPoint ipEnd = new IPEndPoint(IPAddress.Any, 0);
byte[] buffer = new byte[1024];
//阻塞模式接收数据
int recNu = client.ReceiveFrom(buffer, ref ipEnd);
if (recNu == 0)
{
//客户端异常退出
}
}
catch (Exception)
{
//客户端异常退出
break;
//throw;
}
}
}
}
/// <summary>
/// 获取本机的默认IP地址
/// </summary>
/// <returns></returns>
private List<string> GetClientIPAddress()
{
List<string> listIP = new List<string>();
try
{
IPAddress[] addressArray = Dns.GetHostAddresses(Dns.GetHostName());
Regex regex = new Regex(@"\b(([01]?\d?\d|2[0-4]\d|25[0-5])\.){3}([01]?\d?\d|2[0-4]\d|25[0-5])\b");
foreach (IPAddress itemStr in addressArray)
{
if (regex.IsMatch(itemStr.ToString(), 0) && listIP.Contains(itemStr.ToString()) == false)
{
listIP.Add(itemStr.ToString());
}
}
}
catch (Exception ex)
{
AddlistViewMsg("获取本地IP地址,错误信息" + ex.Message);
//throw;
}
return listIP;
}
/// <summary>
/// 操作方法
/// </summary>
/// <param name="contr">控件 </param>
/// <param name="funcMethod">操作委托</param>
private void OperaControl(Control contr, OperalControl funcMethod)
{
if (contr.InvokeRequired)
{
contr.Invoke(funcMethod, null);
}
else
{
funcMethod();
}
}
private void AddlistViewMsg(string msgStr)
{
OperaControl(listViewMsg, () => { listViewMsg.AppendText(string.Format("\r\n*{0:HH时MM分ss秒}* {1}\r\n", DateTime.Now, msgStr)); });
}
private void OperatelistViewFriend(InfoEnum operaTpye, string IP, string port, bool IsOnline = true)
{
if (operaTpye == InfoEnum.AddFriend)
{
OperaControl(listViewFriend, () =>
{
if (!listViewFriend.Items.ContainsKey(IP + port))
{
ListViewItem curViewItem = new ListViewItem(new string[] { IP, port, "在线" });
curViewItem.UseItemStyleForSubItems = false;
curViewItem.SubItems[IndexIsOnline].ForeColor = Color.Green;
curViewItem.Name = IP + port;
listViewFriend.Items.Add(curViewItem);
}
});
}
else if (operaTpye == InfoEnum.CheckISOnline)
{
OperaControl(listViewFriend, () =>
{
listViewFriend.BeginUpdate();
foreach (ListViewItem item in listViewFriend.Items)
{
if (item.Name == IP + port)
{
if (IsOnline)
{
item.SubItems[IndexIsOnline].Text = "在线";
item.SubItems[IndexIsOnline].ForeColor = Color.Green;
}
else
{
item.SubItems[IndexIsOnline].Text = "离线";
item.SubItems[IndexIsOnline].ForeColor = Color.Red;
}
break;
}
}
//listViewFriend.Refresh();
listViewFriend.EndUpdate();
});
}
else if (operaTpye == InfoEnum.DeleteFriend)
{
OperaControl(listViewFriend, () =>
{
foreach (ListViewItem item in listViewFriend.Items)
{
if (item.Name == IP + port)
{
listViewFriend.Items.Remove(item);
break;
}
}
});
}
}
/// <summary>
/// 添加好友
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnAddFriend_Click(object sender, EventArgs e)
{
if (txtLocalIP.Text == txtFriendIP.Text && txtFriendPort.Text == txtLocalPort.Text)
{
MessageBox.Show("不能添加自己为好友!");
return;
}
bool addFriendRet = SendData(InfoEnum.AddFriend, "添加好友", txtFriendIP.Text, txtFriendPort.Text);
if (addFriendRet)
{
OperatelistViewFriend(InfoEnum.AddFriend, txtFriendIP.Text, txtFriendPort.Text);
AddlistViewMsg(string.Format(" 添加好友成功 {0}[{1}]", txtFriendIP.Text, txtFriendPort.Text));
}
else
{
MessageBox.Show("添加好友失败!");
}
}
private bool SendData(InfoEnum operalType, string SendStr, string serverIP, string serverPort)
{
bool retSend = false;
byte[] sendBytes = Encoding.UTF8.GetBytes(string.Format("{0}{1}{2}{1}{3}{1}{4}", (int)operalType, SplitChar, MyAddress.ToString(), LocalHostPort, SendStr));
//添加判断如果不是同一个网段直接返回false
if (serverIP.Remove(serverIP.LastIndexOf('.'))!=MyAddress.ToString().Remove(MyAddress.ToString().LastIndexOf('.')))
{
return retSend;
}
try
{
IPEndPoint serverIEP = new IPEndPoint(IPAddress.Parse(serverIP), int.Parse(serverPort));
TcpClient client = new TcpClient(new IPEndPoint(MyAddress, 0));
client.Connect(serverIEP);
client.Client.Send(sendBytes);
retSend = true;
client.Close();
}
catch (Exception)
{
return retSend;
}
return retSend;
}
/// <summary>
/// 发送消息事件
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void txtSendMsg_KeyDown(object sender, KeyEventArgs e)
{
if (e.Control && e.KeyCode == Keys.Return)
{
ISTrigSendEvent = true;
if (listViewFriend.CheckedItems.Count <= 0)
{
MessageBox.Show("请先选择好友!");
}
else if (txtSendMsg.Text.Length <= 0)
{
MessageBox.Show("请输入发送信息!");
}
else
{
foreach (ListViewItem item in listViewFriend.CheckedItems)
{
bool ret = SendData(InfoEnum.Messages, txtSendMsg.Text, item.SubItems[IndexIP].Text, item.SubItems[IndexPort].Text);
if (!ret)
{
//发送信息失败 好友下线
OperatelistViewFriend(InfoEnum.CheckISOnline, item.SubItems[IndexIP].Text, item.SubItems[IndexPort].Text, false);
MessageBox.Show(string.Format("发送给{0}:{1}送消息失败,好友已经下线!", item.SubItems[IndexIP].Text, item.SubItems[IndexPort].Text));
}
else
{
//更新好友状态 在线
OperatelistViewFriend(InfoEnum.CheckISOnline, item.SubItems[IndexIP].Text, item.SubItems[IndexPort].Text, true);
AddlistViewMsg(string.Format("发送{0}[{1}]消息:{2}", item.SubItems[IndexIP].Text, item.SubItems[IndexPort].Text, txtSendMsg.Text));
}
}
}
}
}
private void txtSendMsg_TextChanged(object sender, EventArgs e)
{
if (ISTrigSendEvent)
{
txtSendMsg.Text = txtSendMsg.Text.TrimEnd(new char[] { '\r', '\n' });
ISTrigSendEvent = false;
txtSendMsg.Select(txtSendMsg.Text.Length, 0);
}
}
/// <summary>
/// 启动刷新好友
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnFlushOnline_Click(object sender, EventArgs e)
{
int timerVal;
bool retTrybool = int.TryParse(txtFlushTime.Text, out timerVal);
if (!retTrybool)
{
MessageBox.Show("输入定时刷新时间无效!");
return;
}
FlushSleepTime = timerVal;
FlushThreadIsLoop = true;
FlushThread = new Thread(FlushFriendOnline);
FlushThread.IsBackground = true;
FlushThread.Start();
btnFlushOnline.Enabled = false;
}
/// <summary>
/// 线程刷新好友是否在线
/// </summary>
void FlushFriendOnline()
{
while (FlushThreadIsLoop)
{
List<ClientNetINfo> tempList = new List<ClientNetINfo>();
OperaControl(listViewFriend, () =>
{
foreach (ListViewItem item in listViewFriend.Items)
{
ClientNetINfo entity = new ClientNetINfo();
entity.IP = item.SubItems[IndexIP].Text;
entity.Port = item.SubItems[IndexPort].Text;
tempList.Add(entity);
}
});
foreach (ClientNetINfo item in tempList)
{
bool ret = SendData(InfoEnum.CheckISOnline, "检测是否在线", item.IP, item.Port);
OperatelistViewFriend(InfoEnum.CheckISOnline, item.IP, item.Port, ret);
}
Thread.Sleep(FlushSleepTime);
}
}
private void btnStopFlushOnline_Click(object sender, EventArgs e)
{
FlushThreadIsLoop = false;
if (FlushThread != null && FlushThread.IsAlive)
{
FlushThread.Abort();
}
btnFlushOnline.Enabled = true;
}
private void ChangeLocalIPList()
{
if (IPListIndex < LocalHostIPList.Count - 1)
{
IPListIndex++;
}
else
{
IPListIndex = 0;
}
}
/// <summary>
/// 切换本地IP地址
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void btnSwitchIP_Click(object sender, EventArgs e)
{
ChangeLocalIPList();
IsloopFlag = false;
if (ServerListener != null)
{
ServerListener.Stop();
}
ProcWorkThread.Abort();
ServerListener = null;
AddlistViewMsg(string.Format("{0}:{1}退出监听", txtLocalIP.Text, txtLocalPort.Text));
Thread.Sleep(10);
//开启监听
if (LocalHostPort.ToString() != txtLocalPort.Text)
{
LocalHostPort = int.Parse(txtLocalPort.Text);
}
IsloopFlag = true;
ProcWorkThread = new Thread(ListenClient);
ProcWorkThread.IsBackground = true;
ProcWorkThread.Start();
}
private List<string> GetLocalAreaOnlineIPs()
{
List<string> IPList = new List<string>();
IPAddress[] localhostIPs = Dns.GetHostAddresses(Dns.GetHostName()).Where<IPAddress>(ret => ret.AddressFamily.ToString() == "InterNetwork").ToArray();
string localIPStr = string.Empty;
Ping textPing = new Ping();
PingReply pingReply = null;
byte[] data = { 0 };
foreach (IPAddress itemIPstr in localhostIPs)
{
localIPStr = itemIPstr.ToString();
//截取IP网段
string IPSegment = localIPStr.Remove(localIPStr.LastIndexOf('.'));
for (int idx = 1; idx < 255; idx++)
{
string pingIP = IPSegment + "." + idx;
pingReply = textPing.Send(pingIP, 5, data);
if (pingReply.Status == IPStatus.Success)
{
IPList.Add(pingIP);
}
}
}
return IPList;
}
/// <summary>
///保存好友信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void FrmText_FormClosing(object sender, FormClosingEventArgs e)
{
List<ClientNetINfo> tempList = new List<ClientNetINfo>();
tempList.Add(new ClientNetINfo() { IP = txtLocalIP.Text, Port = txtLocalPort.Text });
foreach (ListViewItem item in listViewFriend.Items)
{
ClientNetINfo entity = new ClientNetINfo();
entity.IP = item.SubItems[IndexIP].Text;
entity.Port = item.SubItems[IndexPort].Text;
tempList.Add(entity);
}
//xml 序列化
SerializeToXMl(SaveUserInfoPath, tempList);
}
/// <summary>
/// XML序列化
/// </summary>
/// <param name="path"></param>
/// <param name="obj"></param>
private void SerializeToXMl(string path, object obj)
{
XmlSerializer xmlSerializer = new XmlSerializer(obj.GetType());
string strSerial = string.Empty;
using (StringWriter strWriter = new StringWriter())
{
xmlSerializer.Serialize(strWriter, obj);
strSerial = strWriter.ToString();
}
string rexStr = Convert.ToBase64String(Encoding.UTF8.GetBytes(strSerial));
using (StreamWriter write = new StreamWriter(path))
{
write.Write(rexStr);
}
}
/// <summary>
/// XML反序列化
/// </summary>
/// <param name="path"></param>
/// <param name="type"></param>
/// <returns></returns>
private object DeserializeXmL(string path, Type type)
{
XmlSerializer deSerial = new XmlSerializer(type);
string readStr = string.Empty;
using (StreamReader reader = new StreamReader(path, Encoding.UTF8))
{
readStr = reader.ReadToEnd();
}
byte[] readByte = Convert.FromBase64String(readStr);
MemoryStream MemoStream = new MemoryStream(readByte);
using (StreamReader readerEnd = new StreamReader(MemoStream, Encoding.UTF8))
{
return deSerial.Deserialize(readerEnd);
}
}
//右键删除好友
private void DeleteToolStripMenuItem_Click(object sender, EventArgs e)
{
if (listViewFriend.SelectedItems.Count != 1)
{
MessageBox.Show("请先选择删除的好友!");
return;
}
DialogResult result = MessageBox.Show("确认要删除好友吗?", "删除好友", MessageBoxButtons.OKCancel);
if (result == DialogResult.OK)
{
ListViewItem livs = listViewFriend.SelectedItems[0];
string ipStr=livs.SubItems[IndexIP].Text;
string PortStr=livs.SubItems[IndexPort].Text;
bool retDel = SendData(InfoEnum.DeleteFriend, "把你删除了",ipStr ,PortStr );
if (retDel)
{
//删除成功
OperatelistViewFriend(InfoEnum.DeleteFriend, ipStr, PortStr);
AddlistViewMsg(string.Format(" 主动删除好友{0}[{1}]成功!", ipStr, PortStr));
}
else
{
//删除失败
OperatelistViewFriend(InfoEnum.CheckISOnline, ipStr, PortStr,false);
MessageBox.Show("删除好友失败!");
}
}
}
//复制端口号
private void CopyPortToolStripMenuItem_Click(object sender, EventArgs e)
{
if (listViewFriend.SelectedItems.Count != 1)
{
MessageBox.Show("请先选择要复制的端口号!");
return;
}
ListViewItem livs = listViewFriend.SelectedItems[0];
Clipboard.SetText(livs.SubItems[IndexPort].Text);
}
}
public enum InfoEnum
{
Unknown = 0,
AddFriend = 1,
CheckISOnline = 2,
Messages = 3,
DeleteFriend = 4,
}
public class ClientNetINfo
{
public string IP { get; set; }
public string Port { get; set; }
}
}
加粗样式
完整示例下载链接:https://download.csdn.net/download/weixin_43542114/12651028