Socket案例
来源:互联网 发布:淘宝哪家莆田鞋好 编辑:程序博客网 时间:2024/04/29 11:15
服务器端:
using System;
using System.Collections;
using System.Collections.Specialized;
using System.Text;
using System.Threading;
using System.Net.Sockets;
using System.Net;
using System.Runtime.Serialization;
using System.Runtime.Serialization.Formatters.Binary;
using System.IO;
namespace EasyChat_Server
{
class Listener
{
#region 字段定义
/// <summary>
/// 服务器程序使用的端口,默认为8888
/// </summary>
private int _port = 8888;
/// <summary>
/// 接收数据缓冲区大小64K
/// </summary>
private const int _maxPacket = 64 * 1024;
/// <summary>
/// 服务器端的监听器
/// </summary>
private TcpListener _tcpl = null;
/// <summary>
/// 保存所有客户端会话的哈希表
/// </summary>
private Hashtable _transmit_tb = new Hashtable();
#endregion
#region 服务器方法
/// <summary>
/// 关闭监听器并释放资源
/// </summary>
public void Close()
{
if (_tcpl != null)
{
_tcpl.Stop();//如果不为空 就停止 tcplistener
}
//关闭客户端连接并清理资源
if (_transmit_tb.Count != 0)//客户端会话的哈希表
{
foreach (Socket session in _transmit_tb.Values)
{
session.Shutdown(SocketShutdown.Both);
}
_transmit_tb.Clear();
_transmit_tb = null;
}
}
/// <summary>
/// 配置监听端口号
/// </summary>
public void GetConfig()
{
string portParam;
Console.Write("请输入监听端口,直接回车则接受默认端口8888: ");
//portParam = Console.ReadLine();
portParam = Console.ReadLine();
if (portParam != string.Empty)
{
if (!int.TryParse(portParam, out _port) || _port < 1023 || _port > 65535)//很是精炼的语句
{
_port = 8888;
Console.WriteLine("端口号不合法,默认端口号被接受!");
}
}
}
/// <summary>
/// 序列化在线列表,向客户端返回序列化后的字节数组
/// </summary>
/// <returns>序列化后的字节数组</returns>
private byte[] SerializeOnlineList()
{
StringCollection onlineList = new StringCollection();
foreach (object o in _transmit_tb.Keys)
{
onlineList.Add(o as string);//转换语句
}
IFormatter format = new BinaryFormatter();//以二进制格式将对象或整个连接对
//象图形序列化和反序列化。
MemoryStream stream = new MemoryStream();//创建其支持存储区为内存的流
format.Serialize(stream, onlineList); //保持到内存流 将对象或具有给定根的对象图形序列化为所提供的流
byte[] ret = stream.ToArray(); //
stream.Close();
return ret;
}
/// <summary>
/// 提取命令
/// 格式为两个一位整数拼接成的字符串。
/// 第一位为0表示客户机向服务器发送的命令,为1表示服务器向客户机发送的命令。
/// 第二位表示命令的含义,具体如下:
/// "01"-离线
/// "02"-请求在线列表
/// "03"-请求对所有人闪屏振动
/// "04"-请求对指定用户闪屏振动
/// "05"-请求广播消息
/// default-转发给指定用户
/// </summary>
/// <param name="s">要解析的包含命令的byte数组,只提取前两个字节</param>
/// <returns>拼接成的命令</returns>
private string DecodingBytes(byte[] s)
{
return string.Concat(s[0].ToString(), s[1].ToString());
}
/// <summary>
/// 线程执行体,转发消息-------------------
/// </summary>
/// <param name="obj">传递给线程执行体的用户名,用以与用户通信</param>
private void ThreadFunc(object obj)
{
//通过转发表得到当前用户套接字
Socket clientSkt = _transmit_tb[obj] as Socket;
while (true)
{
try
{
//接受第一个数据包。
//仅有两种情况,一为可以识别的命令格式,否则为要求转发给指定用户的用户名。
//这里的实现不够优雅,但不失为此简单模型的一个解决之道。
byte[] _cmdBuff = new byte[128];
clientSkt.Receive(_cmdBuff);
string _cmd = DecodingBytes(_cmdBuff);
/// "01"-离线
/// "02"-请求在线列表
/// "03"-请求对所有人闪屏振动
/// "04"-请求对指定用户闪屏振动
/// "05"-请求广播消息
/// default-转发给指定用户
switch (_cmd)
{
case "01":
{
_transmit_tb.Remove(obj);
string svrlog = string.Format("用户 {0} 在 {1} 已断开... 当前在线人数: {2}/r/n/r/n", obj, DateTime.Now, _transmit_tb.Count);
Console.WriteLine(svrlog);
//向所有客户机发送系统消息
foreach (DictionaryEntry de in _transmit_tb)
{
string _clientName = de.Key as string;
Socket _clientSkt = de.Value as Socket;
_clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));//给其他用户通知现在上线的用户
}
Thread.CurrentThread.Abort();
break;
}
case "02":
{
byte[] onlineBuff = SerializeOnlineList();
//先发送响应信号,用于客户机的判断,"11"表示服务发给客户机的更新在线列表的命令
clientSkt.Send(new byte[] { 1, 1 });
clientSkt.Send(onlineBuff);
break;
}
case "03"://向每个用户发送
{
string displayTxt = string.Format("用户{0}发送了一个闪屏振动。/r/n/r/n", obj);
foreach (DictionaryEntry de in _transmit_tb)
{
string _clientName = de.Key as string;
Socket _clientSkt = de.Value as Socket;
if (!_clientName.Equals(obj))
{
//先发送响应信号,用于客户机的判断,"12"表示服务发给客户机的闪屏振动的命令
_clientSkt.Send(new byte[] { 1, 2 });
_clientSkt.Send(Encoding.Unicode.GetBytes(displayTxt));
}
}
break;
}
case "04"://向指定用户发送
{
string _receiver = null;
byte[] _receiverBuff = new byte[128];
clientSkt.Receive(_receiverBuff);//获取指定用户名
_receiver = Encoding.Unicode.GetString(_receiverBuff).TrimEnd('/0');
string displayTxt = string.Format("用户 {0} 发送了一个闪屏振动。/r/n/r/n", obj);
//通过转发表查找接收方的套接字
if (_transmit_tb.ContainsKey(_receiver))
{
Socket receiverSkt = _transmit_tb[_receiver] as Socket;
receiverSkt.Send(new byte[] { 1, 2 });
receiverSkt.Send(Encoding.Unicode.GetBytes(displayTxt));
}
else
{
string sysMessage = string.Format("[系统消息]您刚才的闪屏振动没有发送成功。/r/n可能原因:用户 {0} 已离线或者网络阻塞。/r/n/r/n", _receiver);
clientSkt.Send(Encoding.Unicode.GetBytes(sysMessage));
}
break;
}
case "05":
{
byte[] _msgBuff = new byte[_maxPacket];
clientSkt.Receive(_msgBuff);
foreach (DictionaryEntry de in _transmit_tb)
{
string _clientName = de.Key as string;
Socket _clientSkt = de.Value as Socket;
if (!_clientName.Equals(obj))
{
_clientSkt.Send(_msgBuff);
}
}
break;
}
default:
{
//以上都不是则表明第一个包是接收方用户名,继续接受第二个消息正文数据包
string _receiver = Encoding.Unicode.GetString(_cmdBuff).TrimEnd('/0');
byte[] _packetBuff = new byte[_maxPacket];
clientSkt.Receive(_packetBuff);
if (_transmit_tb.ContainsKey(_receiver))
{
//通过转发表查找接收方的套接字
Socket receiverSkt = _transmit_tb[_receiver] as Socket;
receiverSkt.Send(_packetBuff);
}
else
{
string sysMessage = string.Format("[系统消息]您刚才的内容没有发送成功。/r/n可能原因:用户 {0} 已离线或者网络阻塞。/r/n/r/n", _receiver);
clientSkt.Send(Encoding.Unicode.GetBytes(sysMessage));
}
break;
}
}
}
catch (SocketException)
{
_transmit_tb.Remove(obj);
string svrlog = string.Format("用户 {0} 的客户端在 {1} 意外终止!当前在线人数:{2}/r/n/r/n", obj, DateTime.Now, _transmit_tb.Count);
Console.WriteLine(svrlog);
//向所有客户机发送系统消息
foreach (DictionaryEntry de in _transmit_tb)
{
string _clientName = de.Key as string;
Socket _clientSkt = de.Value as Socket;
_clientSkt.Send(Encoding.Unicode.GetBytes(svrlog));
}
Console.WriteLine();
Thread.CurrentThread.Abort();
}
}
}
/// <summary>
/// 启动监听,轮询监听客户机请求并将客户端套接字存入转发表
/// </summary>
public void StartUp()
{
IPAddress _ip = Dns.GetHostAddresses(Dns.GetHostName())[0];//可能有多个,此时的IP是本地IP
_tcpl = new TcpListener(_ip, _port);
_tcpl.Start();//开始侦听传入的连接请求。
Console.WriteLine("服务器已启动,正在监听.../n");
Console.WriteLine(string.Format("服务器IP:{0}/t端口号:{1}/n", _ip, _port));
while (true)
{
byte[] packetBuff = new byte[_maxPacket];// 接收数据缓冲区大小64K
//AcceptSocket 是一个阻止方法,该方法返回可用于发送和接收数据的 Socket。
//返回的 Socket 是使用远程主机的 IP 地址和端口号初始化的。
//您可以使用 Socket 类中任何可用的 Send 和 Receive 方法与远程主机进行通信。
Socket newClient = _tcpl.AcceptSocket();//本地TcpListener 接受新的请求
//返回的 Socket 是使用远程主机的 IP 地址和端口号初始化的
newClient.Receive(packetBuff);//将接受的远程SOCKET,将数据存入接受缓冲区
string userName = Encoding.Unicode.GetString(packetBuff).TrimEnd('/0');
//验证是否为唯一用户,有了就发送失败命令给请求客户
if (_transmit_tb.Count != 0 && _transmit_tb.ContainsKey(userName))
{
newClient.Send(Encoding.Unicode.GetBytes("cmd::Failed"));
continue;
}
else
{
newClient.Send(Encoding.Unicode.GetBytes("cmd::Successful"));
}
//将新连接加入转发表并创建线程为其服务
_transmit_tb.Add(userName, newClient);
string svrlog = string.Format("用户 {0} 在 {1} 已连接... 当前在线人数: {2}/r/n/r/n", userName, DateTime.Now, _transmit_tb.Count);
Console.WriteLine(svrlog);
Thread clientThread = new Thread(new ParameterizedThreadStart(ThreadFunc));
clientThread.Start(userName);
}
}
#endregion
}
}
客户端:
登录:
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Net;
using System.Net.Sockets;
using System.Windows.Forms;
namespace EasyChat
{
public partial class login_frm : Form
{
/// <summary>
/// IP地址
/// </summary>
private IPAddress _ipAddr;
#region 登录窗体构造函数
/// <summary>
/// 构造函数,自动生成
/// </summary>
public login_frm()
{
InitializeComponent();
}
#endregion
#region 登录窗体的私有方法
/// <summary>
/// 验证登录信息
/// </summary>
/// <returns>验证结果</returns>
private bool ValidateInfo()
{
if (user_tb.Text.Trim() == string.Empty)
{
MessageBox.Show("请填写用户名!",
"提示",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return false;
}
if (!IPAddress.TryParse(svrip_tb.Text, out _ipAddr))
{
MessageBox.Show("IP地址不合法!",
"提示",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return false;
}
int _port;
if (!int.TryParse(svrport_tb.Text, out _port))
{
MessageBox.Show("端口号不合法!",
"提示",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return false;
}
else
{
if (_port < 1024 || _port > 65535)
{
MessageBox.Show("端口号不合法!",
"提示",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return false;
}
}
return true;
}
/// <summary>
/// 取消,关闭窗体
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void cancel_btn_Click(object sender, EventArgs e)
{
this.Close();
}
/// <summary>
/// 登录
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void login_btn_Click(object sender, EventArgs e)
{
//验证数据合法性
if (!ValidateInfo())
{
return;
}
int port = int.Parse(svrport_tb.Text);
//向服务器发出连接请求
TCPConnection conn = new TCPConnection(_ipAddr, port);
TcpClient _tcpc = conn.Connect();
if (_tcpc == null)
{
MessageBox.Show("无法连接到服务器,请重试!",
"错误",
MessageBoxButtons.OK,
MessageBoxIcon.Exclamation);
}
else
{
NetworkStream netstream = _tcpc.GetStream();//提供用于访问网络的基本数据流
//向服务器发送用户名以确认身份
netstream.Write(Encoding.Unicode.GetBytes(user_tb.Text), 0, Encoding.Unicode.GetBytes(user_tb.Text).Length);
//得到登录结果
byte[] buffer = new byte[50];
netstream.Read(buffer, 0, buffer.Length);//该方法将数据读入 buffer 参数并返回成功读取的字节数。如果没有可以读取的数据,则 Read 方法返回 0。
string connResult = Encoding.Unicode.GetString(buffer).TrimEnd('/0');
if (connResult.Equals("cmd::Failed"))
{
MessageBox.Show("您的用户名已经被使用,请尝试其他用户名!",
"提示",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
else
{
string svrskt = svrip_tb.Text + ":" + svrport_tb.Text;
chat_frm chatFrm = new chat_frm(user_tb.Text, netstream, svrskt);//一个巧妙的参数传递方法
chatFrm.Owner = this;
this.Hide();
chatFrm.Show();
}
}
}
/// <summary>
/// 初始化登录信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void login_frm_Load(object sender, EventArgs e)
{
svrip_tb.Text = "10.1.10.153";
svrport_tb.Text = "8888";
user_tb.Focus();
}
#endregion
}
}
聊天:
using System;
using System.Collections;
using System.Collections.Specialized;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Net.Sockets;//++++
using System.Windows.Forms;
using System.Threading;//++++
using System.Runtime.Serialization;//++++
using System.Runtime.InteropServices;//++++
using System.IO;
using System.Runtime.Serialization.Formatters.Binary;//++++
using System.Media;//+++++
namespace EasyChat
{
public partial class chat_frm : Form
{
#region 私有字段
/// <summary>
/// 当前用户名
/// </summary>
private string _username = null;
/// <summary>
/// 数据缓冲区大小
/// </summary>
private int _maxPacket = 2048;//2K的缓冲区
/// <summary>
/// 用于接受消息的线程
/// </summary>
private Thread _receiveThread = null;
/// <summary>
/// 用于接受和发送的网络流,从登录窗体得到
/// </summary>
private NetworkStream _nws = null;
/// <summary>
/// 服务器套接字的字符串形式,从登录窗体得到
/// </summary>
private string _svrskt = null;
/// <summary>
/// 播放消息提示的播放器
/// </summary>
private SoundPlayer _sp1 = new SoundPlayer(Properties.Resources.msg);
private SoundPlayer _sp2 = new SoundPlayer(Properties.Resources.nudge);
/// <summary>
/// 指示是否最小化到托盘
/// </summary>
private bool _hideFlag = false;
#endregion
#region 聊天窗体构造函数
/// <summary>
/// 构造函数,得到登录窗体的一些信息
/// </summary>
/// <param name="userName">当前用户名</param>
/// <param name="nws">接受和发送消息的网络流</param>
/// <param name="svrskt">服务器套接字的字符串形式</param>
public chat_frm(string userName, NetworkStream nws, string svrskt)
{
InitializeComponent();
_username = userName;
_nws = nws;
_svrskt = svrskt;
}
#endregion
#region 聊天窗体的私有方法
/// <summary>
/// 保存聊天记录
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void save_btn_Click(object sender, EventArgs e)
{
DialogResult ret;
SaveFileDialog sfd = new SaveFileDialog();
sfd.Filter = "文本文件(*.txt)|*.txt";
sfd.AddExtension = true;
if ((ret = sfd.ShowDialog()) == DialogResult.OK)
{
chatrcd_rtb.SaveFile(sfd.FileName, RichTextBoxStreamType.PlainText);
}
}
/// <summary>
/// 清除聊天记录
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void clear_btn_Click(object sender, EventArgs e)
{
DialogResult ret;
ret = MessageBox.Show("确定清除吗?清除后不可恢复。",
"提示",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2);
if (ret == DialogResult.OK)
{
chatrcd_rtb.Clear();
}
}
/// <summary>
/// 向服务器发送离线请求,结束接受消息线程,清理资源并关闭父窗体和自身窗体
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void close_btn_Click(object sender, EventArgs e)
{
DialogResult ret;
ret = MessageBox.Show("确定与服务器断开连接吗?",
"退出",
MessageBoxButtons.OKCancel,
MessageBoxIcon.Question,
MessageBoxDefaultButton.Button2);
if (ret == DialogResult.OK)
{
//向服务器发送离线请求
_nws.Write(new byte[] { 0, 1 }, 0, 2);
//结束接受消息的线程
if (_receiveThread != null)
{
_receiveThread.Abort();
}
//关闭网络流
_nws.Close();
//关闭父窗口及自身===========
this.Owner.Close();
this.Close();
}
}
/// <summary>
/// 提取命令
/// 格式为两个一位整数拼接成的字符串。
/// 第一位为0表示客户机向服务器发送的命令,为1表示服务器向客户机发送的命令。
/// 第二位表示命令的含义,具体如下:
/// "11"-服务器要求客户机更新在线列表
/// "12"-服务器要求客户机做闪屏振动
/// default-接受用户消息或者系统消息的正文
/// </summary>
/// <param name="s">要解析的包含命令的byte数组,只提取前两个字节</param>
/// <returns>拼接成的命令</returns>
private string DecodingBytes(byte[] s)
{
return string.Concat(s[0].ToString(), s[1].ToString());
}
/// <summary>
/// 接受消息的线程执行体
/// </summary>
private void ReceiveMsg()
{
while (true)
{
byte[] packet = new byte[_maxPacket];
_nws.Read(packet, 0, packet.Length);
string _cmd = DecodingBytes(packet);
switch (_cmd)
{
/// "11"-服务器要求客户机更新在线列表
/// "12"-服务器要求客户机做闪屏振动
/// default-接受用户消息或者系统消息的正文
case "11":
{
byte[] onlineBuff = new byte[_maxPacket];
int byteCnt = _nws.Read(onlineBuff, 0, onlineBuff.Length);
IFormatter format = new BinaryFormatter();
MemoryStream stream = new MemoryStream();
stream.Write(onlineBuff, 0, byteCnt);
stream.Position = 0;
StringCollection onlineList = (StringCollection)format.Deserialize(stream);
online_cb.Items.Clear();
foreach (string onliner in onlineList)
{
if (!onliner.Equals(_username))
{
online_cb.Items.Add(onliner);
}
}
break;
}
case "12":
{
Nudge();
break;
}
default:
{
string displaytxt = Encoding.Unicode.GetString(packet);
chatrcd_rtb.AppendText(displaytxt);
_sp1.Play();
break;
}
}
}
}
/// <summary>
/// 启动接受消息线程并显示相关信息
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void chat_frm_Load(object sender, EventArgs e)
{
_receiveThread = new Thread(new ThreadStart(ReceiveMsg));
_receiveThread.Start();
online_cb.Enabled = false;
user_lb.Text = "当前用户:" + _username;
svrskt_lb.Text = "服务器:" + _svrskt;
}
/// <summary>
/// 通过窗体右上角关闭窗体
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void chat_frm_FormClosing(object sender, FormClosingEventArgs e)
{
if (e.CloseReason == CloseReason.UserClosing)
{
e.Cancel = true;
}
if (e.CloseReason == CloseReason.FormOwnerClosing)
{
return;
}
close_btn_Click(sender, e);
}
/// <summary>
/// 发送消息,将接受方用户名和消息正文分开发送,便于服务器端处理
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void send_btn_Click(object sender, EventArgs e)
{
string localTxt = null;
string sendTxt = null;
string msg = msg_tb.Text.Trim();
if (msg == string.Empty)
{
MessageBox.Show("不能发送空消息",
"提示",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
//如果是聊天室模式则向服务器发送广播请求
if (broadcast_rb.Checked)
{
localTxt = string.Format("[广播]您在 {0} 对所有人说:/r/n{1}/r/n/r/n", DateTime.Now, msg);
sendTxt = string.Format("[广播]{0} 在 {1} 对所有人说:/r/n{2}/r/n/r/n", _username, DateTime.Now, msg);
//发送广播请求
_nws.Write(new byte[] { 0, 5 }, 0, 2);
}
else
{
string _receiver = online_cb.Text;
if (_receiver == string.Empty)
{
MessageBox.Show("请选择一个接收者!/n如果没有接受者可选,表明当前只有您一个人在线/t",
"发送消息",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
localTxt = string.Format("[私聊]您在 {0} 对 {1} 说:/r/n{2}/r/n/r/n", DateTime.Now, _receiver, msg);
sendTxt = string.Format("[私聊]{0} 在 {1} 对您说:/r/n{2}/r/n/r/n", _username, DateTime.Now, msg);
//发送接受者用户名
_nws.Write(Encoding.Unicode.GetBytes(_receiver), 0, Encoding.Unicode.GetBytes(_receiver).Length);
}
_nws.Write(Encoding.Unicode.GetBytes(sendTxt), 0, Encoding.Unicode.GetBytes(sendTxt).Length);
chatrcd_rtb.AppendText(localTxt);
msg_tb.Clear();
}
/// <summary>
/// 有新消息来时闪烁任务栏并且保持聊天记录内容滚动到最底端,QQ就是这么玩滴~
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
[DllImport("user32.dll")]
public static extern bool FlashWindow(IntPtr hWnd, bool bInvert);
private void chatrcd_rtb_TextChanged(object sender, EventArgs e)
{
chatrcd_rtb.ScrollToCaret();
if (this.WindowState == FormWindowState.Minimized)
{
FlashWindow(this.Handle, true);
}
}
/// <summary>
/// 当窗口恢复后取消任务栏的闪烁效果
/// 当窗口最小化时判断是否要隐藏到系统托盘
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void chat_frm_SizeChanged(object sender, EventArgs e)
{
switch (this.WindowState)
{
case FormWindowState.Normal:
FlashWindow(this.Handle, false);
break;
case FormWindowState.Minimized:
if (_hideFlag)
{
notifyIcon1.Visible = true;
this.Visible = false;
}
break;
default:
break;
}
}
/// <summary>
/// 在线列表下拉框显示之前向服务器发送请求在线列表的命令
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void online_cb_DropDown(object sender, EventArgs e)
{
_nws.Write(new byte[] { 0, 2 }, 0, 2);
}
/// <summary>
/// 聊天模式改变
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void broadcast_rb_CheckedChanged(object sender, EventArgs e)
{
if (private_rb.Checked)
{
online_cb.Enabled = true;
}
else
{
online_cb.Enabled = false;
}
}
/// <summary>
/// 设置最小化到系统托盘的标记值
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void hide_cb_CheckedChanged(object sender, EventArgs e)
{
_hideFlag = hide_cb.Checked;
}
/// <summary>
/// 产生闪屏振动效果
/// </summary>
private void Nudge()
{
if (notifyIcon1.Visible == true)
{
return;
}
if (this.WindowState == FormWindowState.Minimized)
{
this.WindowState = FormWindowState.Normal;
}
int i = 0;
Point _old = this.Location;
Point _new1 = new Point(_old.X + 2, _old.Y + 2);
Point _new2 = new Point(_old.X - 2, _old.Y - 2);
_sp2.Play();
while (i < 4)
{
this.Location = _new1;
Thread.Sleep(60);
this.Location = _new2;
Thread.Sleep(60);
i++;
}
this.Location = _old;
}
/// <summary>
/// 发送闪屏振动
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void nudge_pb_Click(object sender, EventArgs e)
{
string displayTxt = null;
if (private_rb.Checked && online_cb.Text == string.Empty)
{
MessageBox.Show("非聊天室模式下必须先选择一个接收者!",
"发送闪屏振动",
MessageBoxButtons.OK,
MessageBoxIcon.Information);
return;
}
if (private_rb.Checked)
{
_nws.Write(new byte[] { 0, 4 }, 0, 2);
string _receiver = online_cb.Text;
_nws.Write(Encoding.Unicode.GetBytes(_receiver), 0, Encoding.Unicode.GetBytes(_receiver).Length);
displayTxt = string.Format("[系统提示]您向 {0} 发送了一个闪屏振动。/r/n/r/n", _receiver);
}
else
{
_nws.Write(new byte[] { 0, 3 }, 0, 2);
displayTxt = "[系统提示]您向所有人发送了一个闪屏振动。/r/n/r/n";
}
chatrcd_rtb.AppendText(displayTxt);
Nudge();
}
/// <summary>
/// 以下是系统托盘菜单的处理函数
/// </summary>
/// <param name="sender"></param>
/// <param name="e"></param>
private void close_tsmi_Click(object sender, EventArgs e)
{
close_btn_Click(sender, e);
}
private void notifyIcon1_DoubleClick(object sender, EventArgs e)
{
comeback_tsmi_Click(sender, e);
}
private void comeback_tsmi_Click(object sender, EventArgs e)
{
notifyIcon1.Visible = false;
this.Visible = true;
this.WindowState = FormWindowState.Normal;
this.BringToFront();
}
#endregion
//private void msg_tb_KeyDown(object sender, KeyEventArgs e)
//{
// if (e.KeyCode == Keys.Control && e.KeyValue == 13)
// {
// send_btn.Click += new EventHandler(send_btn_Click);
// send_btn_Click(sender, e);
// }
//}
private void msg_tb_KeyPress(object sender, KeyPressEventArgs e)
{
}
}
}
- Socket案例
- socket案例
- socket案例
- Socket案例
- socket基础案例
- socket案例一
- socket案例二
- java socket编程案例
- C# Socket客户端 案例
- C# Socket服务端 案例
- unity3d socket编程案例
- Linux socket编程案例
- Socket .IO 案例
- 【socket】案例分析
- socket简单案例
- socket小案例
- socket多线程方式案例
- linux c socket 源码案例
- 请问如何得到post 的URL
- .NET中的流
- 星曜解说之紫微星
- SQL数据库同步
- Jetty 报 java.lang.IllegalStateException: Form too large
- Socket案例
- windows下安装perl模块
- 美好生活不等式
- h.264qq群讨论记录
- Const,Const函数,Const变量,函数后面的Const
- struts2中form提交到action中的中文参数乱码问题解决办法
- MyEclipse注册码生成程序
- mysql编码格式转换
- 34步优化 SQL语句