1、 发送端向接收端发送要接受文件的文件名 发送端从文件中读取到缓冲区并发送给客户端 客户端和服务端的用于发送和接受的缓冲区的大小是相同的,为了实现两个的大小相同可在输出文件之前由发送方告诉接受方本次输出所用的缓冲区的大小。每次发送之前应将剩余文件的大小与缓冲区的大小做比较,当剩余文件的大小小于缓冲区的大小时,调整缓冲区的大小同剩余文件相同,将剩余的文件发送到接收端。 关闭文件流3.视频传输技术 视频的传输过程利用了avicap32.dll和user32.dll完成摄像头的视频采集。avicap32.dll和user32.dll是Window API 应用程序接口的相关模块。avicap32.dl
2、l接口可以方便地对摄像头和其他视频硬件进行API电影和视频的截取。主要过程如下所示:(将发起视频的称为客户端) 客户端发起视频连接的请求 客户端打开本地摄像头,每隔10ms向服务端发送采集到的图片,同时接受服务端发送过来的图片 服务端打开本地的摄像头,同时接受客户端发送过来的图片和向客户端发送图片 关闭视频传输流程图如下所示:三、 系统详细设计客户机与服务机之间的通信过程如下所示由上图可知主要的函数为字节数组发送函数、字节数组接收函数、消息发送函数、消息接收函数、文件发送函数、文件接收函数、视频发送函数、视频接收函数。详细介绍如下所示:1.字节数组发送函数SendVarDatapublic s
3、tatic int SendVarData(Socket s, byte data) /函数返回的是发送字节数组的大小 int total = 0; int size = data.Length;/发送数组的大小 int dataleft = size; int sent; byte datasize = new byte4; datasize = BitConverter.GetBytes(size); sent = s.Send(datasize);/首先发送字节数组的大小 while (total size) /循环发送字节数组的主体 sent = s.Send(data, total,
4、 dataleft, SocketFlags.None); total += sent; dataleft -= sent; return total;2. 字节数组接受函数ReceiveVarDatapublic static byte ReceiveVarData(Socket s) /函数返回值是接受的字节数组 int recv; recv = s.Receive(datasize, 0, 4, SocketFlags.None);/首先接受字节数组的大小 int size = BitConverter.ToInt32(datasize, 0);/转换为int型/剩余的大小 byte d
5、ata = new bytesize; /接受主体函数 recv = s.Receive(data, total, dataleft, SocketFlags.None); if (recv = 0) data = null; break; total += recv; dataleft -= recv; return data; 3.消息接受函数ListenMessage() private void ListenMessage() IPAddress myIP = Dns.GetHostAddresses(Dns.GetHostName()0;/获取本机的IP地址 ServerMessag
6、eSocket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); ServerMessageSocket.Bind(new IPEndPoint(myIP, myport2);/绑定端口号 ServerMessageSocket.Listen(10);/等待客户链接 client = ServerMessageSocket.Accept(); IPEndPoint ip1 = (IPEndPoint)client.RemoteEndPoint;/获取对方的IP地址 SendIP = ip
7、1.Address;/将对方的IP地址保存到全局变量中,以后使用 message = DateTime.Now.ToString() + : 客户端+client.RemoteEndPoint+接入n; AddMessage(message);/打印提示消息 while (Flag = true)/接受对方发过来的消息 string Message = 对方: + System.Text.Encoding.Unicode.GetString(TransFile.ReceiveVarData(client) + n AddMessage(Message);4.接受文件的函数ReceiveFile
8、 public void ReceiveFile(Object Myclient) Socket client = (Socket)Myclient; string SendFileName = System.Text.Encoding.Unicode.GetString(TransFile.ReceiveVarData(client);/获得文件名 string Path = SendFileName.Substring(0, SendFileName.LastIndexOf() + 1);/获取目录信息 if (!Directory.Exists(Path)/创建目录 Directory.
9、CreateDirectory(Path); else /如果目录已经存在则删除原有的目录信息 Directory.Delete(Path, true); FileStream MyFileStream = new FileStream(SendFileName, FileMode.Create, FileAccess.Write);/创建一个新文件 int SendedCount = 0;/已发送包的个数 while (true) byte data = TransFile.ReceiveVarData(client); if (data.Length = 0) SendedCount+;
10、/将接收到的数据包写入到文件流对象 MyFileStream.Write(data, 0, data.Length); /关闭文件流 MyFileStream.Close(); 文件传输完成!文件保存在+SendFileName+/打印出提示信息5.发送文件的函数 public void StartSend(Object Path) string file = (string)Path.ToString(); string message = null; try IPEndPoint iep = new IPEndPoint(SendIP, 2052); client2 = new Socke
11、t(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);/创建套接字 client2.Connect(iep);/连接到发送端 FileInfo EzoneFile = new FileInfo(file); FileStream EzoneStream = EzoneFile.OpenRead();/打开文件流 int PacketSize = 10000;/包的大小 int PacketCount = (int)(EzoneStream.Length / (long)PacketSize);/包的数量 int L
12、astDataPacket = (int)(EzoneStream.Length - (long)(PacketSize * PacketCount);/最后一个包的大小 string path = C:Temp + EzoneFile.Name;/发送文件名到客户端 TransFile.SendVarData(client2, System.Text.Encoding.Unicode.GetBytes(path);/数据包 byte data = new bytePacketSize; /开始循环发送数据包 for (int i = 0; i PacketCount; i+) /从文件流读取
13、数据并填充数据包 EzoneStream.Read(data, 0, data.Length); /发送数据包 TransFile.SendVarData(client2, data); /如果还有多余的数据包,则应该发送完毕! if (LastDataPacket != 0) data = new byteLastDataPacket; EzoneStream.Close(); client2.Shutdown(SocketShutdown.Both); catch MessageBox.Show(远程主机未开启!); client2.Close(); 文件发送完毕n6.发送视频函数 pri
14、vate void Send_One_Capture() /将字节数组存放到内存流中 MemoryStream ms = new MemoryStream(); try /将摄像头的一帧数据存放到剪贴板中 myCamera.CaptureWindow(); /从剪贴板中获取图片 data = Clipboard.GetDataObject(); /将截图存放到内存流中 if (data.GetDataPresent(typeof(System.Drawing.Bitmap) bmap = (Image)(data.GetData(typeof(System.Drawing.Bitmap); b
15、map.Save(ms, System.Drawing.Imaging.ImageFormat.Bmp); byte arrImage = ms.GetBuffer();/将内存流转换为字节数组 string array = ms.ToString(); TransFile.SendVarData(client_camera, arrImage); ms.Flush(); catch (Exception ex)视频发送错误! ms.Close();7.视频接受函数 private void listentCamera() Form1.CheckForIllegalCrossThreadCal
16、ls = false;/本机IP地址 ServerMessageSocket.Bind(new IPEndPoint(myIP, camera_port);/监听端口 ServerMessageSocket.Listen(1); Socket client = ServerMessageSocket.Accept(); 对方 + client.RemoteEndPoint + 请求视频n/打印消息 if (single) /接受视频函数的主体 byte buffer = TransFile.ReceiveVarData(client); receiveMS = new MemoryStream
17、(buffer); this.pictureFriend.Image = Image.FromStream(receiveMS);/显示到控件 receiveMS.Close();/关闭内存流 yulan = false; this.buttonSee.Text = 取消预览 LocalVedioShow(); Thread sendshipin = new Thread(sendSP); sendshipin.Start(); client.Close();四、 系统测试及结果1. 服务端软件启动时界面如下所示当服务端软件启动时,首先单击【开启服务】,这样客户端才能连接到服务端上。 消息发送
18、:在消息文本框中输入要发送的消息,单击下面的【发送】即可发送消息。发送的消息会显示在上面的聊天记录文本框中。 文件传输:单击【浏览】,选择要传送的文件,文件选择完毕后单击【发送】 视频聊天:单击【本地预览】可以看到本地视频预览的效果,但客户端连接到服务端时,对方邀请后即可进行视频聊天。2. 客户端软件启动时界面如下所示当服务端启动之后,客户端才可以进行相关的操作: 在“服务方IP”中输入服务端的IP地址,如果测试的是本机就直接输入本机的IP地址,软后单击【启动服务】,便可以连接到服务端,在连接到服务端之后才可以进行其他的相关操作。 消息传输:在消息文本框中输入消息,单击下面的【发送】按钮,便可
19、以将消息发送到服务端,发送的消息显示在上面的文本框中,同时接受的消息也显示在这个文本框中,可以达到聊天的效果。单击【浏览】按钮,选择要发送的文件,文件的路径会显示在他旁边的文本框中,单击发送按钮便可以将文件发送到服务端。 视频传输:当客户端与服务端连接之后便可以进行视频聊天,单击【本地预览】可以进行本地视频的预览,单击【邀请聊天】后,服务端会受到客户端的视频请求,这样之后便可以进行视频聊天了。3. 文字聊天的截图4. 文件传输截图5. 视频聊天截图五、 课程设计总结通过这次课程设计,我对软件开发有了进一步的了解,把理论知识应用于实验中。也让我重新熟悉了C#语言的相关内容,加深了对C#语言知识的
20、深化和用途的理解。通过这次的课程设计,对于TCP/IP协议,套接字的使用、摄像头的启动与应用有了很深入的理解。实验过程中也遇到了很多的问题,如文件的传输、摄像头的驱动、画面的采集等,在上面花费了较多的时间,收集了很多的资料,最总将问题顺利解决。这同时也锻炼了我的解决问题和资料收集的能力。当然,软件中还有很多其他的问题,比如软件关闭后可能会有进程没有关闭等异常情况,这将在后期的维护当中逐步解决。总之,这次的课程设计的顺利完成使我受益匪浅。六、 附录课程设计源代码客户端主要程序代码public partial class Form1 : Form IPAddress SendIP = null;
21、Socket client1;/接收和发送消息的套接字 bool Flag = true;/标示是否开启服务 Socket ServerFileSocket;/文件套接字 Socket ServerMessageSocket;/消息套接字 int myport1 = 2050;/文件发送端口 int myport2 = 2051;/消息监听端口 int myport3 = 2052;/文件监听端口 int camera_port = 2053;/视频监听端口 int camera_port1 = 2054;/视频监听端口2 Thread Listen1;/监听文件线程 Thread Liste
22、n2;/监听消息线程 Thread camera_listen;/监听视频的线程 bool isshipin = false;/是否在视频聊天 string message; Socket client_camera; IDataObject data; Image bmap; bool single =true; MemoryStream receiveMS; WebCamera myCamera = new WebCamera(); public Form1() InitializeComponent(); private void Search_Click(object sender,
23、EventArgs e) if (this.openFileDialog1.ShowDialog() = DialogResult.OK) this.FilePath.Text = this.openFileDialog1.FileName; / /利用委托向RichTextBox中添加信息/summaryparam name=message private delegate void AddMessageDelegate(string message); public void AddMessage(string message) if (richTextBox1.InvokeRequire
24、d) AddMessageDelegate d = AddMessage; richTextBox1.Invoke(d, message); richTextBox1.AppendText(message); private void Send_Click(object sender, EventArgs e) if (this.FilePath.Text.Length = 0)请选择文件! return; string Path = this.FilePath.Text; Thread SendFile = new Thread(StartSend); SendFile.Start(this.FilePath.Text); /发送文件函数 Socket client; public void StartSend(Object Path) /指向远程服务端节点 IPEndPoint ipep = new IPEndPoint(SendIP, myport1);
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1