一 : 局域网聊天工具的设计与实现——C#
一 需求分析
1.1 开发背景
在网络越来越发达的今天,人们对网络的依赖越来越多,越来越离不开网络,由此而产生的聊天工具越来越多,类似QQ、网络聊天时一类的聊天系统的发展日新月异。但是,QQ等现有的聊天程序也存在着很大的问题。
比如使用QQ的时候,就对各种弹窗广告深恶痛绝。对于登陆后时不时弹出的打扰窗口,很是厌烦。因此在本次作业下产生了一个制作类似QQ的网络聊天工具并且“无垃圾信息”洁净聊天工具的想法,而且希望通过制作该程序还能更好的学习网络软件编程知识。
1.2 功能要求
(1)登录功能。
(2)客户可以通过服务器转发,实现一对一、一对多和多对多聊天。
(3)实现抖动和声音提醒。
(4)服务器端和客户端程序都能实时显示在线用户数目。
(5)应该具有友好、易用、美观的图形界面。
(6)无垃圾打扰信息
(7)保存和删除聊天信息。
1.3 运行环境
1.本系统基于WINDOWS socket接口设计,适用于WINDOWS XP等系统。
2.但是在WINDOWS 7系统下运行服务器端则会产生IP地址乱码
3.运行环境仅限于局域网,否则无法登陆
1/18
4.偶尔会出现聊天框崩溃闪退情况
1.4 功能实现
1.登录验证功能。对于账号重复等异常,需要提示给用户。
2. 客户通过服务器转发,实现一对一、一对多和多对多聊天。
3. 实时显示目前其它用户的状态,能够提示在线用户数目、状态等。
4. 保存并能察看聊天纪录。
5.申请新的用户号码。
6. 易用、美观的图形界面,实现系统托盘。
7.收到信息时,能够收到声音等提示信息,发送端还能通过发送抖动,提示聊天的对方。
二.项目设计
2/18
2.1程序流图
2.2 概要设计
通过C#,实现网络聊天的功能,采用Windows Socket编程,服务器与客户端采用了TCP/IP连接方式,在设计聊天方案时,实行将所有信息发往服务器端,再由服务器进行分别处理的思路,服务器端是所有信息的中心。
由于服务器端要保存用户信息,我们利用数据库来实现这一功能,因此首先需要建立用
3/18
户信息数据库。
在客户端保存聊天纪录和用户号码这一功能的实现中,采用了文件系统设计。
在信息到来及好友上线时,通过闪动托盘图标和播放不同的音乐进行提示。
建立消息链表来保存用户接收的各种消息。
2.3功能设计
客户端:
1) 登陆功能:建立与服务器的连接并登陆,能显示登陆错误信息。
2) 界面显示:将在线好友显示在好友列表中,并实现系统托盘,加入工具栏便于操作。
3) 聊天功能:与好友聊天。
4) 聊天纪录:能保存聊天纪录,并能察看聊天纪录。
5) 信息提示:闪动托盘图标提示到来信息,并播放不同音乐来提示。
6) 发送窗口抖动,发送端提示聊天的对方。
服务器端:
向各个客户端发布系统消息。
接受来自客户端的各种信息并分别处理。
1) 登陆信息:检查登陆信息是否正确,并向客户端返回登陆信息,如信息正确。就将
在线用户发给该用户,并将该用户的状态发给各在线用户。同时在服务器端显示出来。
2) 聊天信息:转发给消息指定的用户。
3) 申请信息:自动分配8位用户号码,并保存该用户,同时将信息返回给客户端。
4) 用户下线:将此用户下线消息发给各客户端,并改写用户在服务器端的状态。
4/18
程序中主要变量及函数的功能说明如下:
客户端:
private void login_btn_Click(object sender, EventArgs e) --- 登陆到服务器
private void svrip_tb_TextChanged(object sender,EventArgs e)设置要连接的服务器的地址端口
private void chatrcd_rtb_TextChanged(object sender, EventArgs e)-- 显示好友发送的信息 private void send_btn_Click(object sender, EventArgs e) ---- 给好友发送信息 private void user_tb_TextChanged(object sender, EventArgs e) ----- 申请新的用户
private void chatrcd_rtb_TextChanged(object sender, EventArgs e) ---- 显示服务器消息 private void msg_tb_TextChanged(object sender, EventArgs e) ----- 显示消息输入文本
private void nudge_pb_Click(object sender, EventArgs e)------发送窗口抖动
private void broadcast_rb_CheckedChanged(object sender, EventArgs e)------聊天模式的变更 private void hide_cb_CheckedChanged(object sender, EventArgs e)-------最小化到托盘
服务器端:
用户及发送信息结构体类型:
public void StartUp()-------服务器启动,并且实时更新用户在线信息
public void GetConfig()------配置服务器端口号等信息
private void ThreadFunc(object obj)-----系统对于发送消息、发送抖动等的异常的处理 public void Close()--------关闭服务器
2.4 详细设计 2.4.1界面设计
客户端
1) 登陆界面
5/18
2) 显示当 前状
态
3) 最小化到托盘
4) 发送抖动
5) 聊天模式变更
6) 发送接收消息
7) 禁止登陆名重复
6/18
客户端
1) 服务器启动配置端口号
7/18
2) 实时更新在线用户信息
2.4.2程序结构设计
如概要设计反映。
三.编码实现
3.1、客户端
a)登陆
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, 8/18
Encoding.Unicode.GetBytes(user_tb.Text).Length);
//得到登录结果
byte[] buffer = new byte[50];
netstream.Read(buffer, 0, buffer.Length);
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();
}
}
}
b)发送消息
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",
9/18
_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);
10/18
}
}
/// <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) 11/18
二 : C#局域网聊天工具、消息推送实现思路与源码
C#局域网聊天工具怎么实现?
1. 网络通讯编程的基础便是协议,信息的发送常用的协议有面向连接的TCP协议,以及不面向连接的UDP协议
2. TCP:TransmissionControlProtocol传输控制协议,其是一种面向连接的、可靠的字节流服
务。[www.61k.com]面向连接意味着两个使用TCP的应用(通常是一个客户和一个服务器)在彼此交换数据之前必须先建立一个TCP连接。这一过程与打电话很相似,先拨号振铃,等待对方摘机说“喂”,然后才说明是谁。
3. UDP:UserDatagramProtocol用户数据报协议(RFC768),UDP传送数据前并不与对方建立连
接,即UDP是无连接的,在传输数据前,发送方和接收方相互交换信息使双方同步。
4. 系统也要定义自己的通讯协议,来完成一些系统的功能,如用户上,下线的通知,都要定义
自己的通讯协议来完成相应的功能!也可以称这种自定义的协议为“命令”.
5. 下面以著名的飞鸽传书为例,说明其自定义的协议(命令)
IPMSG_NOOPERATION不进行任何操作
IPMSG_BR_ENTRY用户上线
IPMSG_BR_EXIT用户退出
IPMSG_ANSENTRY通报在线
IPMSG_SENDMSG发送消息
IPMSG_RECVMSG通报收到消息
IPMSG_GETFILEDATA请求通过TCP传输文件
IPMSG_RELEASEFILES停止接收文件
IPMSG_GETDIRFILES请求传输文件夹以“IPMSG_BR_ENTRY用户上线”和“IPMSG_ANSENTRY通报在线”为例说明命令处理流程:当程序启动时,命令IPMSG_BR_ENTRY被广播到网络中,向所有在线的用户提示一个新用户的到达(即表示“我来了”);所有在线用户将把该新上线用户添加到自己的用户列表中,并向该新上线用户发送IPMSG_ANSENTRY命令(即表示“我在线”);该新上线用户接收到IPMSG_ANSENTRY命令后即将在线用户添加到自己的用户列表中。
PS:根据本系统的特征,可以在聊天部分采用UDP协议,在文件传输,视频,语音功能上采用TCP协议
6. 程序启动就要发送广播消息,如何发送广播消息,以及C#如何实现广播.
第一部分.什么是广播地址,以及广播地址怎么计算
1.1广播地址是什么?
主机号全为1,用于向一个网络内的所有主机发送信息的IP地址.如:受限的广播地址是255.255.255.255。该地址用于主机配置过程中IP数据报的目的地址,此时,主机可能还不知道它所在网络的网络掩码,甚至连它的IP地址也不知道。在任何情况下,路由器都不转发目的地址为受限的广播地址的数据报,这样的数据报仅出现在本地网络中。
PS:一般无特殊要求广播地址选择255.255.255.255即可.
1.2计算方法
首先计算网络地址=IP地址逻辑与(&)子网掩码
先把IP,子网掩码转为2进制,然后进行逻辑与运算,得出网络地址
例:
IP192.168.1.3子网掩码255.255.0.0
IP转二进制11000000.10100100.00000001.00000011
子网掩码11111111.11111111.00000000.00000000
与运算后11000000.10100100.00000000.00000000
192.168.0.0这就是网络地址,其中子网掩码全1对应为网络号,全0对应的是主机号,即192.168.0.0对应的网络号为192.168,主机号为0.0.将网络地址主机部分全取反后得到的地址便是广播地址:
广播地址11000000.10100100.11111111.11111111
换成10进制则为192.168.0.0
ipmsg C#局域网聊天工具、消息推送实现思路与源码
第二部分.C#利用UDP协议如何实现广播
2.1如何实现UDP广播,直接举例说明:
button1_Click时使用了UDP广播向外发送了数据
RecData()在后台接受UDP协议的消息
//UDP通过广播实现群发功能
namespace BroadcastExample
{
public partial class Form1:Form
{
delegate void AppendStringCallback(stringtext);
AppendStringCallback appendstringcallback;
//使用的接收端口51008
///<summary>
///端口号
///</summary>
private int port=51008;
///<summary>
///udp连接对象
///</summary>
private UdpClient udpclient;
public Form1()
{
InitializeComponent();
appendstringcallback = new AppendStringCallback(AppendString); }
///<summary>
///委托对象的处理过程
///</summary>
///<paramname="text"></param>
private void AppendString(stringtext)
{
if(richtextBox2.InvokeRequired==true)
{
this.Invoke(appendstringcallback,text);
}
else
{
richtextBox2.AppendText(text+"rn");
}
}
///<summary>
///在后台运行的接收线程
///</summary>
private void RecData()
{
//本机指定端口接收
udpclient=new UdpClient(port);
IPEndPoint remote=null;
ipmsg C#局域网聊天工具、消息推送实现思路与源码
//接收从远程主机发送过来的信息
while(true)
{
try
{
//关闭udpclient时此句会产生异常
byte[]bytes= www.61k.com (refremote);
stringstr=Enco www.61k.com (bytes,0,bytes.Length);
AppendString(string.Format("来自{0}:{1}",remote,str));
}
catch
{
//退出循环,结束线程
break;
}
}
}
privatevoidForm1_Load(objectsender,EventArgse)
{
//创建一个线程接收接收远程主机发来的信息
Thread mythread=new Thread(new ThreadStart(RecData));
//将线程设为后台运行
mythread.IsBackground=true;
mythread.Start();
}
private void Form1_FormClosing(objectsender,FormClosingEventArgse) {
udpclient.Close();
}
private void button1_Click(objectsender,EventArgse)
{
UdpClient myUdpclient=newUdpClient();
try
{
IPEndPoint iep=new IPEndPoint(IPAddress.Broadcast,port);
byte[]bytes= www.61k.com .Enco www.61k.com ( www.61k.com ); myUdpclient.Send(bytes,bytes.Length,iep);
textBox1.Clear();
myUdpclient.Close();
textBox1.Focus();
}
catch(Exceptionerr)
{
MessageBox.Show( www.61k.com ,"发送失败");
}
finally
{
myUdpclient.Close();
ipmsg C#局域网聊天工具、消息推送实现思路与源码
}
}
}
}
启动主程序时,同时启动UDP的监听,这时应该使用集合来做为消息队列的缓存,以便用户能在任何时候浏览到消息.这个集合一般在主程序中定义,而用户接受消息,一般我们会弹出窗口给用户来浏览消息,以及在新窗口中回复消息,那如何将主窗口中的消息,传递到消息显示窗体中呢?
如何是Web( www.61k.com )我们可以封装到form中传值,或者request传值,甚至可以在URL中接参数直接传值,而winform中窗体传值以上方法就都不在能用了.
在windowsform之间传值,我总结了有四个方法:全局变量、属性、窗体构造函数和delegate。(www.61k.com) 第一个全局变量:
这个最简单,只要把变量描述成static就可以了,在form2中直接引用form1的变量,代码如下: 在form1中定义一个static变量publicstaticinti=9;
Form2中的钮扣按钮如下:
privatevoidbutton1_Click(objectsender,System.EventArgse)
{
www.61k.com =Form1.i.ToString();
}
第二个方法是利用属性:
假设我们需要点击主窗体FMMain中的某一个按钮时打开子窗体FMChild并将某一个值传给子窗体FMChild,一般情况下,我们点击按钮显示子窗体FMChild的代码为: FMChildfmChild=newFMChild();fmChild.ShowDialog();fmChild.Dispose();
如果我们需要将主窗体FMMain中的stringstrValueA的值传给FMChild,那么我们首先对strValueA进行如下处理:
privatestringstrValueA;publicstringStrValueA{get{returnstrValueA;}set{strValueA=value;}}
使其成为主窗体FMMain的一个属性,接着修改显示子窗体的代码为以下两种的其中一种。 方法一:
FMChildfmChild=newFMChild();fmChild.ShowDialog(this);fmChild.Dispose(); 方法二:
FMChildfmChild=newFMChild();FMChild.Owner=this;fmChild.ShowDialog();fmChild.Dispose();
然后在修改子窗体FMChild中申明一个主窗体FMMain对象,
FMMainfmMain;
在需要使用主窗体FMMain的stringstrValueA的地方加上如下代码:
fmMain=(FMMain)this.Owner;
这样,就可以获得主窗体FMMain中strValueA的值了。
这时,如果你需要将子窗体FMChild中的stringstrValueB传给主窗体FMMain,同样处理stringstrValueB.
privatestringstrValueB;publicstringStrValueB{get{returnstrValueB;}set{strValueB=value;}}
那么你在关闭子窗体代码fmChild.Dispose();后,可以写一些代码来保存或者处理FMChild的strValueB,例如:
stringstrTmp=fmChild.StrValueB;
ipmsg C#局域网聊天工具、消息推送实现思路与源码
第三个方法是用构造函数:
Form1的button按钮这样写:
privatevoidbutton1_Click(objectsender,System.EventArgse)
{
Form2temp=newForm2(9);
temp.Show();
}
Form2的构造函数这样写:
publicForm2(inti)
{
InitializeComponent();
www.61k.com =i.ToString();
}
第四个方法是用delegate,代码如下:
Form2中先定义一个delegate
publicdelegatevoidreturnvalue(inti);
publicreturnvalueReturnValue;
form2中的button按钮代码如下:
privatevoidbutton1_Click(objectsender,System.EventArgse)
{
if(ReturnValue!=null)
ReturnValue(8);
}
Form1中的button按键如下:
privatevoidbutton1_Click(objectsender,System.EventArgse)
{
Form2temp=newForm2();
www.61k.com =new www.61k.com (showvalue);
temp.Show();
}
privatevoidshowvalue(inti)
{
www.61k.com =i.ToString();
}
点击form2的button,form1中的textbox中的值就会相应变化。(www.61k.com]
在这四个方法中,
第一个是双向传值,也就是说,form1和form2改变i的值,另一方也会受到影响。 第二个方法可以单向也可以双向传值。
第三个方法是form1->form2单向传值。
第四个方法是form2->form1单向传值。
现在很多程序都有托盘功能,而我们的聊天工具更是如此,无论是QQ,旺旺,飞鸽传书等等,都是
ipmsg C#局域网聊天工具、消息推送实现思路与源码
以托盘的形式工作在后台,对消息进行监听的.而VS2005给我们提供了现成的控件,来完成托盘的功能,下面我结合代码讲解下项目中可能用到的托盘技巧.
1.如何实现托盘功能:
在VS2005中直接添加notifyIcon控件,然后设置下icon属性,给其设置个图标即可,使用托盘功能. 但是托盘并不能实现我们要求的功能,具体的功能实现,需要我们手工添加代码实现.
2.如何最小化时自动到托盘
private void Form1_Resize(objectsender,System.EventArgse)
{
if(this.WindowState==FormWindowState.Minimized)
{
this.Visible=false;
www.61k.com .Visible=true;
}
}
3.如何双击托盘恢复原状
private void notifyIcon1_Click(objectsender,System.EventArgse)
{
this.Visible=true;
this.WindowState= www.61k.com ;
www.61k.com .Visible=false;
}
4.实现托盘的闪烁功能(如QQ有消息时的闪烁)
(1).首先我们在空白窗体中拖入一个NotifyIcon控件和定时控件
privateSystem.Win www.61k.com ;
privateSystem.Windows.Forms.Timertimer1;
(2).其次,我们准备两张ico图片,用来显示在任务栏,其中一张可用透明的ico图片,分别叫做1.ico和2.ico;并且建立两个icon对象分别用来存放两个ico图片;
privateIconico1=newIcon("1.ico");
privateIconico2=newIcon("2.ICO");//透明的图标
(3).在Form_load中初始化notifyicon:
privatevoidForm1_Load(objectsender,System.EventArgse)
{
www.61k.com .Icon=ico1;//设置程序刚运行时显示在任务栏的图标
www.61k.com =true;//将定时控件设为启用,默认为false;
}
(4).先设置一个全局变量i,用来控制图片索引,然后创建定时事件,双击定时控件就可以编辑 inti=0;
privatevoidtimer1_Tick(objectsender,System.EventArgse)
{
//如果i=0则让任务栏图标变为透明的图标并且退出
if(i<1)
{
www.61k.com .Icon=ico2;
i++;
return;
}
//如果i!=0,就让任务栏图标变为ico1,并将i置为0;
else
www.61k.com .Icon=ico1;
ipmsg C#局域网聊天工具、消息推送实现思路与源码
i=0;
}
由于消息传输要求较低,而且为了简化聊天的步骤,在局域网聊天中,采用UDP是非常好的选择.因为UDP可以不用连接,在获取用户列表后,直接点击用户名就可以发送消息,减少了等待连接等繁琐
1.UDP发送信息
namespaceXChat.SendMes
{
public class MsgSend
{
private UdpClient udp=null;
private int PORT;
private IPEndPoint endP=null;
public MsgSend()
{
this.PORT=58888;
}
publicMsgSend(intport)
{
this.PORT=port;
}
///<summary>
///发送信息
///</summary>
///<paramname="hostName">要发送到的主机名</param>
///<paramname="message">要发送的信息</param>
publicvoidSendMessage(stringhostName,stringmessage)
{
this.udp=newUdpClient();
endP=newIPEndPoint( www.61k.com (hostName).AddressList[0],PORT);
try
{
//byte[]b=Enco www.61k.com (hostName);
byte[]b=Enco www.61k.com (message);
udp.Send(b,b.Length,endP);
}
catch
{
System.Win www.61k.com .Show("发送出错!");
}
finally
{
this.udp.Close();
}
}
ipmsg C#局域网聊天工具、消息推送实现思路与源码
}
}
要使用时直接new MsgSend().SendMessage(主机名,消息);
2.UDP接收消息
namespaceXChat.SendMes
{
//设置消息到前台的委托
public delegate voidSet Message(stringmes); public class MsgRecive
{
private int PORT;
private UdpClient udp=null;
private Thread recThread=null;
private IPEndPoint ipep=null;
private SetMessages etMes;
public MsgRecive()
{
this.PORT=58888;
}
publicMsgRecive(intport)
{
this.PORT=port;
}
///<summary>
///开启后台接受消息线程
///</summary>
///<paramname="setMes">传入设置消息的委托</param> publicvoidStartReciveMsg(SetMessagesetMes) {
this.setMes=setMes;
udp=newUdpClient(PORT);
recThread=newThread(newThreadStart(ReciveMsg)); recThread.Start();
}
///<summary>
///关闭后台消息接收线程
///</summary>
publicvoidCloseReciveMsg()
{
recThread.Abort();
//recThread.Join();
udp.Close();
}
privatevoidReciveMsg()
{
while(true)
{
ipmsg C#局域网聊天工具、消息推送实现思路与源码
//这句很重要,否则CPU很容易100%
Thread.Sleep(500);
byte[] b = www.61k.com (refipep);
string message=Enco www.61k.com (b,0,b.Length);
this.setMes(message);
}
}
}
}
在前台private MsgRecive mr=null;
public xchatFrm()
{
??
www.61k.com =newMsgRecive(port);
www.61k.com (newSetMessage(GetMes));
??
}
这几天一直想写一个类似QQ文件发送的东西,上网找了一些资料,都不是很理想,下面我把我的思路和基本实现代码说下。(www.61k.com]
为了把问题说清楚,把一些变量都直接附值了,并没有通过输入附值
private string path = "F:SmartMovie.EXE"; //要发送的文件
private Socket s;
private void listen()
{
string ip = "127.0.0.1"; //远程IP 这里定义为自己的机器
IPAddress[] ih = www.61k.com (ip); //获得IP列表
IPAddress newip = ih[0]; //获取IP地址
int port = 6789; //定义端口
IPEndPoint Conncet = new IPEndPoint(newip, port); //构造结点
s = new Socket(AddressFamily.InterNetwork, SocketType.Stream, www.61k.com ); //初始化socket
try
{
s.Connect(Conncet); //连接远程服务器
if (s.Connected) //如果连接成功 s.Connected 则为true 否则为 false
{
Console.WriteLine("连接成功");
ipmsg C#局域网聊天工具、消息推送实现思路与源码
Thread t = new Thread(new ThreadStart(set)); //创建进程
t.Start(); //开始进程
Console.WriteLine("发送完毕")
}
}
catch(NullReferenceException e)
{
Console.WriteLine("{0}",e);
}
private void set() //创建set函数
{
Console.WriteLine("开始发送数据");
byte[] b = new byte[10000000]; //创建文件缓冲区,这里可以认为文件的最大值
FileStream file = File.Open(path, FileMode.Open, www.61k.com ); //创建文件流
int start = 0;
int end = (int)file.Length; //获取文件长度 文件传送如果有需要超过int的范围估计就要改写FileStream类了
try
{
while (end != 0)
{
int count = www.61k.com (b, start, end); //把数据写进流 start += count;
end -= count;
}
while (start != 0)
{
int n = s.Send(b, end, start, www.61k.com ); //用Socket的Send方法发送流
end += n;
start -= n;
}
file.Close(); //关闭文件流
s.Close(); //关闭Socket
}
catch (NullReferenceException e)
{
Console.WriteLine("{0}", e);
}
}
ipmsg C#局域网聊天工具、消息推送实现思路与源码
这样文件发送的模型就实现了
接下去实现文件的接收,首先要确定对方发送文件的长度,其实上面的那段还要加入发送文件长度的功能,实现很简单,就是发送int变量end ,然后要求接收代码返回一个Boolean确定是否发送,这里为了更简明的说清楚原理并没有实现
private void get()
{
string path = "G:da.exe"; //接收的文件
FileStream file = new FileStream(path, FileMode.OpenOrCreate, FileAccess.Write); //写入文件流
TcpListener listen = new TcpListener(6789); //监听端口
Socket s1 = new Socket(AddressFamily.InterNetwork, SocketType.Stream, www.61k.com ); //定义Socket并初始化
try
{
listen.Start(); //开始监听
s1 = listen.AcceptSocket(); //获取Socket连接
byte[] data = new byte[10000000]; //定义缓冲区
int longer = data.Length;
int start = 0;
int mid = 0;
if ( www.61k.com ) //确定连接
{
Console.WriteLine("连接成功");
int count = www.61k.com (data, start, longer, www.61k.com ); //把接收到的byte存入缓冲区
mid += count;
longer -= mid;
while (count != 0)
{
count = www.61k.com (data, mid, longer, www.61k.com );
mid += count;
longer -= mid;
}
file.Write(data, 0, 1214134); //写入文件,1214134为文件大小,可以用socket发送获得,代码前面已经说明。(www.61k.com]
s1.Close();
file.Close();
}
}
catch(NullReferenceException e)
{
Console.WriteLine("{0}",e);
}
}
三 : Windows局域网聊天工具怎么使用
其实在Windows中已经嵌入局域网聊天的工具,只是由于对话框生硬,交互能力不强,就不受人重视了。Windows局域网聊天工具的使用方法其实很简单,下面由我们告诉你!
依次点击开始,运行,然后输入cmd后回车:
输入 net start messenger 后回车,即可开启信使服务:
在命令框中输入net view查看局域网上的计算机名:
在命令框中输入net send -3"信息"即可在对方的主机上显示信息:
如下图所示,为发送到客户机上的信息为Hello!,发送时间为2002年7月19日9点48分36秒。
。www.61k.com。 本文标题:局域网聊天工具-局域网聊天工具的设计与实现——C#61阅读| 精彩专题| 最新文章| 热门文章| 苏ICP备13036349号-1