基于TCP的局域网视频聊天程序课程设计Word下载.docx
《基于TCP的局域网视频聊天程序课程设计Word下载.docx》由会员分享,可在线阅读,更多相关《基于TCP的局域网视频聊天程序课程设计Word下载.docx(41页珍藏版)》请在冰豆网上搜索。
![基于TCP的局域网视频聊天程序课程设计Word下载.docx](https://file1.bdocx.com/fileroot1/2023-1/30/a0b004ac-bbf0-4c39-b09e-67bb27e89a01/a0b004ac-bbf0-4c39-b09e-67bb27e89a011.gif)
发送端向接收端发送要接受文件的文件名
发送端从文件中读取到缓冲区并发送给客户端
客户端和服务端的用于发送和接受的缓冲区的大小是相同的,为了实现两个的大小相同可在输出文件之前由发送方告诉接受方本次输出所用的缓冲区的大小。
每次发送之前应将剩余文件的大小与缓冲区的大小做比较,当剩余文件的大小小于缓冲区的大小时,调整缓冲区的大小同剩余文件相同,将剩余的文件发送到接收端。
关闭文件流
3.视频传输技术
视频的传输过程利用了avicap32.dll和user32.dll完成摄像头的视频采集。
avicap32.dll和user32.dll是WindowAPI应用程序接口的相关模块。
avicap32.dll接口可以方便地对摄像头和其他视频硬件进行API电影和视频的截取。
主要过程如下所示:
(将发起视频的称为客户端)
客户端发起视频连接的请求
客户端打开本地摄像头,每隔10ms向服务端发送采集到的图片,同时接受服务端发送过来的图片
服务端打开本地的摄像头,同时接受客户端发送过来的图片和向客户端发送图片
关闭视频传输
流程图如下所示:
三、系统详细设计
客户机与服务机之间的通信过程如下所示
由上图可知主要的函数为字节数组发送函数、字节数组接收函数、消息发送函数、消息接收函数、文件发送函数、文件接收函数、视频发送函数、视频接收函数。
详细介绍如下所示:
1.字节数组发送函数SendVarData
publicstaticintSendVarData(Sockets,byte[]data)
{
//函数返回的是发送字节数组的大小
inttotal=0;
intsize=data.Length;
//发送数组的大小
intdataleft=size;
intsent;
byte[]datasize=newbyte[4];
datasize=BitConverter.GetBytes(size);
sent=s.Send(datasize);
//首先发送字节数组的大小
while(total<
size)
{//循环发送字节数组的主体
sent=s.Send(data,total,dataleft,SocketFlags.None);
total+=sent;
dataleft-=sent;
}
returntotal;
2.字节数组接受函数ReceiveVarData
publicstaticbyte[]ReceiveVarData(Sockets)
{//函数返回值是接受的字节数组
intrecv;
recv=s.Receive(datasize,0,4,SocketFlags.None);
//首先接受字节数组的大小
intsize=BitConverter.ToInt32(datasize,0);
//转换为int型
//剩余的大小
byte[]data=newbyte[size];
{//接受主体函数
recv=s.Receive(data,total,dataleft,SocketFlags.None);
if(recv==0)
data=null;
break;
total+=recv;
dataleft-=recv;
returndata;
}
3.消息接受函数ListenMessage()
privatevoidListenMessage()
IPAddressmyIP=Dns.GetHostAddresses(Dns.GetHostName())[0];
//获取本机的IP地址
ServerMessageSocket=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
ServerMessageSocket.Bind(newIPEndPoint(myIP,myport2));
//绑定端口号
ServerMessageSocket.Listen(10);
//等待客户链接
client=ServerMessageSocket.Accept();
IPEndPointip1=(IPEndPoint)client.RemoteEndPoint;
//获取对方的IP地址
SendIP=ip1.Address;
//将对方的IP地址保存到全局变量中,以后使用
message=DateTime.Now.ToString()+"
:
客户端"
+client.RemoteEndPoint+"
接入\n"
;
AddMessage(message);
//打印提示消息
while(Flag==true)//接受对方发过来的消息
stringMessage="
对方:
"
+System.Text.Encoding.Unicode.GetString(TransFile.ReceiveVarData(client))+"
\n"
AddMessage(Message);
4.接受文件的函数ReceiveFile
publicvoidReceiveFile(ObjectMyclient)
Socketclient=(Socket)Myclient;
stringSendFileName=System.Text.Encoding.Unicode.GetString(TransFile.ReceiveVarData(client));
//获得[文件名]
stringPath=SendFileName.Substring(0,SendFileName.LastIndexOf("
\\"
)+1);
//获取目录信息
if(!
Directory.Exists(@Path))//创建目录
Directory.CreateDirectory(@Path);
else
{//如果目录已经存在则删除原有的目录信息
Directory.Delete(@Path,true);
FileStreamMyFileStream=newFileStream(SendFileName,FileMode.Create,FileAccess.Write);
//创建一个新文件
intSendedCount=0;
//已发送包的个数
while(true)
byte[]data=TransFile.ReceiveVarData(client);
if(data.Length==0)
SendedCount++;
//将接收到的数据包写入到文件流对象
MyFileStream.Write(data,0,data.Length);
//关闭文件流
MyFileStream.Close();
文件传输完成!
文件保存在"
+SendFileName+"
//打印出提示信息
5.发送文件的函数
publicvoidStartSend(ObjectPath)
stringfile=(string)Path.ToString();
stringmessage=null;
try
IPEndPointiep=newIPEndPoint(SendIP,2052);
client2=newSocket(AddressFamily.InterNetwork,SocketType.Stream,ProtocolType.Tcp);
//创建套接字
client2.Connect(iep);
//连接到发送端
FileInfoEzoneFile=newFileInfo(file);
FileStreamEzoneStream=EzoneFile.OpenRead();
//打开文件流
intPacketSize=10000;
//包的大小
intPacketCount=(int)(EzoneStream.Length/((long)PacketSize));
//包的数量
intLastDataPacket=(int)(EzoneStream.Length-((long)(PacketSize*PacketCount)));
//最后一个包的大小
stringpath="
C:
\\Temp\\"
+EzoneFile.Name;
//发送[文件名]到客户端
TransFile.SendVarData(client2,System.Text.Encoding.Unicode.GetBytes(path));
//数据包
byte[]data=newbyte[PacketSize];
//开始循环发送数据包
for(inti=0;
i<
PacketCount;
i++)
//从文件流读取数据并填充数据包
EzoneStream.Read(data,0,data.Length);
//发送数据包
TransFile.SendVarData(client2,data);
//如果还有多余的数据包,则应该发送完毕!
if(LastDataPacket!
=0)
data=newbyte[LastDataPacket];
EzoneStream.Close();
client2.Shutdown(SocketShutdown.Both);
catch
MessageBox.Show("
远程主机未开启!
);
client2.Close();
文件发送完毕\n"
6.发送视频函数
privatevoidSend_One_Capture()
//将字节数组存放到内存流中
MemoryStreamms=newMemoryStream();
try
//将摄像头的一帧数据存放到剪贴板中
myCamera.CaptureWindow();
//从剪贴板中获取图片
data=Clipboard.GetDataObject();
//将截图存放到内存流中
if(data.GetDataPresent(typeof(System.Drawing.Bitmap)))
bmap=(Image)(data.GetData(typeof(System.Drawing.Bitmap)));
bmap.Save(ms,System.Drawing.Imaging.ImageFormat.Bmp);
byte[]arrImage=ms.GetBuffer();
//将内存流转换为字节数组
stringarray=ms.ToString();
TransFile.SendVarData(client_camera,arrImage);
ms.Flush();
catch(Exceptionex)
视频发送错误!
ms.Close();
7.视频接受函数
privatevoidlistentCamera()
Form1.CheckForIllegalCrossThreadCalls=false;
//本机IP地址
ServerMessageSocket.Bind(newIPEndPoint(myIP,camera_port));
//监听端口
ServerMessageSocket.Listen
(1);
Socketclient=ServerMessageSocket.Accept();
对方"
+client.RemoteEndPoint+"
请求视频\n"
//打印消息
if(single)
{//接受视频函数的主体
byte[]buffer=TransFile.ReceiveVarData(client);
receiveMS=newMemoryStream(buffer);
this.pictureFriend.Image=Image.FromStream(receiveMS);
//显示到控件
receiveMS.Close();
//关闭内存流
yulan=false;
this.buttonSee.Text="
取消预览"
LocalVedioShow();
Threadsendshipin=newThread(sendSP);
sendshipin.Start();
client.Close();
四、系统测试及结果
1.服务端软件启动时界面如下所示
当服务端软件启动时,首先单击【开启服务】,这样客户端才能连接到服务端上。
●消息发送:
在消息文本框中输入要发送的消息,单击下面的【发送】即可发送消息。
发送的消息会显示在上面的聊天记录文本框中。
●文件传输:
单击【浏览】,选择要传送的文件,文件选择完毕后单击【发送】
●视频聊天:
单击【本地预览】可以看到本地视频预览的效果,但客户端连接到服务端时,对方邀请后即可进行视频聊天。
2.客户端软件启动时界面如下所示
当服务端启动之后,客户端才可以进行相关的操作:
●在“服务方IP”中输入服务端的IP地址,如果测试的是本机就直接输入本机的IP地址,软后单击【启动服务】,便可以连接到服务端,在连接到服务端之后才可以进行其他的相关操作。
●消息传输:
在消息文本框中输入消息,单击下面的【发送】按钮,便可以将消息发送到服务端,发送的消息显示在上面的文本框中,同时接受的消息也显示在这个文本框中,可以达到聊天的效果。
单击【浏览】按钮,选择要发送的文件,文件的路径会显示在他旁边的文本框中,单击发送按钮便可以将文件发送到服务端。
●视频传输:
当客户端与服务端连接之后便可以进行视频聊天,单击【本地预览】可以进行本地视频的预览,单击【邀请聊天】后,服务端会受到客户端的视频请求,这样之后便可以进行视频聊天了。
3.文字聊天的截图
4.文件传输截图
5.视频聊天截图
五、课程设计总结
通过这次课程设计,我对软件开发有了进一步的了解,把理论知识应用于实验中。
也让我重新熟悉了C#语言的相关内容,加深了对C#语言知识的深化和用途的理解。
通过这次的课程设计,对于TCP/IP协议,套接字的使用、摄像头的启动与应用有了很深入的理解。
实验过程中也遇到了很多的问题,如文件的传输、摄像头的驱动、画面的采集等,在上面花费了较多的时间,收集了很多的资料,最总将问题顺利解决。
这同时也锻炼了我的解决问题和资料收集的能力。
当然,软件中还有很多其他的问题,比如软件关闭后可能会有进程没有关闭等异常情况,这将在后期的维护当中逐步解决。
总之,这次的课程设计的顺利完成使我受益匪浅。
六、附录课程设计源代码
客户端主要程序代码
publicpartialclassForm1:
Form
IPAddressSendIP=null;
Socketclient1;
//接收和发送消息的套接字
boolFlag=true;
//标示是否开启服务
SocketServerFileSocket;
//文件套接字
SocketServerMessageSocket;
//消息套接字
intmyport1=2050;
//文件发送端口
intmyport2=2051;
//消息监听端口
intmyport3=2052;
//文件监听端口
intcamera_port=2053;
//视频监听端口
intcamera_port1=2054;
//视频监听端口2
ThreadListen1;
//监听文件线程
ThreadListen2;
//监听消息线程
Threadcamera_listen;
//监听视频的线程
boolisshipin=false;
//是否在视频聊天
stringmessage;
Socketclient_camera;
IDataObjectdata;
Imagebmap;
boolsingle=true;
MemoryStreamreceiveMS;
WebCameramyCamera=newWebCamera();
publicForm1()
InitializeComponent();
privatevoidSearch_Click(objectsender,EventArgse)
if(this.openFileDialog1.ShowDialog()==DialogResult.OK)
this.FilePath.Text=this.openFileDialog1.FileName;
///<
summary>
///利用委托向RichTextBox中添加信息
/summary>
paramname="
message"
>
<
/param>
privatedelegatevoidAddMessageDelegate(stringmessage);
publicvoidAddMessage(stringmessage)
if(richTextBox1.InvokeRequired)
AddMessageDelegated=AddMessage;
richTextBox1.Invoke(d,message);
richTextBox1.AppendText(message);
privatevoidSend_Click(objectsender,EventArgse)
if(this.FilePath.Text.Length==0)
请选择文件!
return;
stringPath=this.FilePath.Text;
ThreadSendFile=newThread(StartSend);
SendFile.Start(this.FilePath.Text);
//发送文件函数
Socketclient;
publicvoidStartSend(ObjectPath)
//指向远程服务端节点
IPEndPointipep=newIPEndPoint(SendIP,myport1);