C# 程序用 0 填充整个 1023 字节的 NetworkStream,第一个字节正确
C# Program filling NetworkStream with 0's for an entire 1023 bytes, with first byte correct
目前我正在编写一个 C# 程序来满足计算机网络 class 项目,该程序可以用任何语言编写(我选择了 C#)并且必须执行某种网络多媒体过程。它可以是点对点的或基于客户端-服务器的。
我选择将我的应用程序设为点对点。客户端使用 UDP 将其 connect/disconnect 广播到本地网络上的其他客户端,然后使用 TCP 在彼此之间发送和接收 .WAV 文件。
根据连接请求,客户端将接受 TCP 连接并开始从发送客户端读取数据。
数据全部读取完毕后,客户端就可以播放.WAV文件了。
我目前一直在尝试修复我的程序中的一个错误,该错误要求将 .WAV 文件发送两次而不是一次,以便接收方获取文件并播放它。
这导致我 运行 陷入一个我之前 运行 陷入的问题:Wave header is corrupt.
之前,我 运行 解决了这个问题,因为在播放 .WAV 文件时,我没有将流位置设置为 0。这第一次修复了它。
但是,原因现在更有趣了,因为我正在尝试修复一个不同的错误。
这次的原因是.WAV文件流中的数据被分割了。一开始,数据的第一个字节是正确的(通过使用十六进制编辑器查看我正在尝试 send/receive 的 .WAV 文件中的字节来验证)然后流中填充了 1023 个字节的 0 .之后,.WAV 文件的其余数据没有拆分。
(另一次 send/recv 试验显示第一个字节再次正确,但接下来的 1023 个字节不同步且放错了位置。接下来的 1023 个字节不是 0x00,而是来自另一段放错地方的文件。)
我不知道是什么原因造成的,并已使用 Wireshark 尝试找出问题所在。我在接收端进行了一次wireshark抓包,发现发送的第一个数据包只有一个字节的数据:0x52.
下一个数据包有 1460 字节。在 NetworkStream 中的那 1460 个字节之后没有 0x00 的拆分。
下面提供的是我的程序代码。它也可以在 Github https://github.com/cparks1/ECE369ProjB-MultimediaGUI
上找到
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets; // For network programming
using System.Net; // For network programming
using System.Media; // For playing .WAV files
using System.IO; // For playing .WAV files (SoundPlayer in System.Media accepts either a filepath or an IO stream.)
namespace ProjectBMultimediaGUI
{
public partial class Form1 : Form
{
private delegate void ObjectDelegate(string msg, IPEndPoint sender);
private delegate void LabelChanger(string msg);
const int PUBLISH_PORT_NUMBER = 8030; // Port number used for publish (UDP communications)
const int TCP_PORT_NUMBER = 8031; // Port number used for the rest of communications (TCP communications)
IPAddress me = GetLocalIP(); // me is the IPAddress that your machine currently owns on the local network
const string CLIENT_ANNOUNCE = "[ECE 369] Multimedia client publish"; // UDP datagram to be sent when the client is announcing itself
const string CLIENT_DISCONNECT = "[ECE 369] Multimedia client disconnect"; // UDP datagram to be sent when the client is announcing that it is disconnecting
UdpClient pub = new UdpClient(PUBLISH_PORT_NUMBER, AddressFamily.InterNetwork); // Creates a new UDP client capable of communicating on a network on port defined by const, via IPv4 addressing
IPEndPoint UDP_BROADCAST = new IPEndPoint(IPAddress.Broadcast, PUBLISH_PORT_NUMBER); // Broadcast address and port
TcpListener tlisten = new TcpListener(IPAddress.Any,TCP_PORT_NUMBER); // Sets up a listener that looks for TCP connections
TcpClient tcprecvr;
Stream wavstream = new MemoryStream(); // Initializes a memory stream that will hold .wav file data when being written to. Will be reinitialized in packet receiving functions
Timer tmr = new Timer(); // Timer used to announce client on the local network every 250 ms
SoundPlayer splayer;
bool isClosing = false; // Used to determine if program is closing
byte[] readbuf = new byte[1024];
long wavpos = 0;
public Form1()
{
InitializeComponent();
#region Timer Setup
tmr.Interval = 250;
tmr.Start();
tmr.Tick += new EventHandler(tmr_Tick);
#endregion
}
private void tmr_Tick(object sender, EventArgs e)
{
if (!isClosing)
Announce_Client_Connect(); // Announce the client is connected every 250 ms
}
private void playpauseBUT_MouseClick(object sender, MouseEventArgs e)
{
Button sbut = (sender as Button);
splayer = new SoundPlayer(wavstream);
if (sbut.ImageIndex == 0) // If the PLAY button was clicked
{ // Initiate play functions
if (wavstream.CanRead && wavstream.Length > 0)
{
splayer.Stream.Position = 0;
splayer.Play();
}
sbut.ImageIndex = 1; // Change the button to show PAUSE
}
else // If the PAUSE button was clicked
{
splayer.Stop();
sbut.ImageIndex = 0; // Change the button to show PLAY
}
}
private void Form1_Load(object sender, EventArgs e)
{
butIML.ImageSize = new Size(playpauseBUT.Size.Width-1,playpauseBUT.Size.Height-1); // This ensures the play and pause buttons are always the same size as the button they are encased in
stopBUT.Size = playpauseBUT.Size; // Ensures the stop button is the same size as the play/pause button.
stopBUT.Location = new Point(stopBUT.Location.X, playpauseBUT.Location.Y);
pub.AllowNatTraversal(false); // Disables the ability for the program to communicate with the outside world, for security purposes
try { pub.BeginReceive(new AsyncCallback(RecvPub), null); }
catch(Exception err) { MessageBox.Show("An error occurred!\n"+err.ToString()); Application.Exit(); }
tlisten.AllowNatTraversal(false);
BeginListening(); // Begins listening for attempts to connect to the client via TCP
Announce_Client_Connect();
}
private void BeginListening()
{
tlisten.Start();
tlisten.BeginAcceptTcpClient(new AsyncCallback(RecvTcp), null);
}
private void stopBUT_MouseClick(object sender, MouseEventArgs e)
{
splayer.Stop();
playpauseBUT.ImageIndex = 0; // Change the play/pause button to show PLAY
}
private void mainMS_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(new Pen(Color.Black), mainMS.Left, mainMS.Bottom-1, mainMS.Right, mainMS.Bottom-1); // Draws a border on the bottom of the main menu strip.
e.Graphics.DrawLine(new Pen(Color.Black), mainMS.Left, mainMS.Top, mainMS.Right, mainMS.Top); // Draws a border on the top of the menu strip.
}
private void RecvPub(IAsyncResult res) // Function used to handle received UDP messages
{
IPEndPoint recv = new IPEndPoint(IPAddress.Any, PUBLISH_PORT_NUMBER);
byte[] message = null;
string dmessage;
if (!isClosing)
message = pub.EndReceive(res, ref recv);
if(message != null) // If a message was received
{
ObjectDelegate del = new ObjectDelegate(HandleUDPDatagram);
dmessage = Encoding.ASCII.GetString(message);
del.Invoke(dmessage, recv);
HandleUDPDatagram(dmessage, recv);
}
if (!isClosing)
pub.BeginReceive(new AsyncCallback(RecvPub), null);
}
private void RecvTcp(IAsyncResult res)
{
LabelChanger lblchgr = new LabelChanger(dataavailable); // Used for cross thread operations on dataavailLBL
wavstream = new MemoryStream(); // Clear the wav stream, we don't want two wav files in one stream, it would cause errors.
lblchgr.Invoke("Data unavailable."); // No data available yet.
//tcprecvr = tlisten.AcceptTcpClient(); // Accept the incoming TCP connection.
tcprecvr = tlisten.EndAcceptTcpClient(res); // Create a new TCP connection with the requester
NetworkStream stream = tcprecvr.GetStream(); // Get the TCP network stream
if (stream.CanRead)
{
while (!stream.DataAvailable) ;
stream.BeginRead(readbuf, 0, readbuf.Length, new AsyncCallback(RecvTCPData), null);
}
else
{
tcprecvr.Close();
MessageBox.Show("An error has occurred. Unable to read incoming TCP stream.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
}
private void RecvTCPData(IAsyncResult res)
{
LabelChanger lblchgr = new LabelChanger(dataavailable); // Used for cross thread operations on dataavailLBL
wavpos = 0; // Reset the WAV stream position
NetworkStream stream = tcprecvr.GetStream(); // Get the TCP data stream
int nbytes = stream.EndRead(res); // Get the number of bytes read
if (nbytes == 0) // Finished reading
{
tcprecvr.Close(); // Close the TCP connection
lblchgr.Invoke("Data available!"); // Inform the user there is a .WAV file to be played
BeginListening(); // Begin listening to connection requests again
//return;
}
else // Not finished reading, data in buffer
{
wavstream.Write(readbuf, 0, readbuf.Length); // Write WAV data to wav stream
stream.BeginRead(readbuf, 0, readbuf.Length, new AsyncCallback(RecvTCPData), null); // begin read again
}
}
private void dataavailable(string msg)
{
if(InvokeRequired)
{
LabelChanger method = new LabelChanger(dataavailable);
Invoke(method, msg);
return;
}
dataavailLBL.Text = "Data available!";
}
private void HandleUDPDatagram(string msg, IPEndPoint sender) // Used for handling UDP messages
{
if (!sender.Address.Equals(me)) // Verifies the UDP datagram received isn't from your own machine.
{ //This is done because some UDP datagrams are sent to the broadcast address, which means we receive what we've sent. We obviously don't want packets from ourselves so we block them.
if (InvokeRequired && !isClosing) // Used for handling thread magic. Please don't ask me to explain this.
{
ObjectDelegate method = new ObjectDelegate(HandleUDPDatagram);
Invoke(method, msg, sender);
return;
}
switch (msg)
{
case CLIENT_ANNOUNCE: // If we've received a client connection message
if (!hostsLB.Items.Contains(sender.Address)) // If the client is not already in the list box
hostsLB.Items.Add(sender.Address); // Add the client to the listbox of clients
break;
case CLIENT_DISCONNECT: // If we've received a client disconnection message
if (hostsLB.Items.Contains(sender.Address)) // If the client is in the listbox
hostsLB.Items.Remove(sender.Address); // Remove the client from the listbox of clients
break;
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
isClosing = true;
Announce_Client_Disconnect(); // Declare your disconnection to the other clients on the network
}
private void Announce_Client_Disconnect()
{
byte[] dgram = Encoding.ASCII.GetBytes(CLIENT_DISCONNECT); // Encode the client disconnection message into an array of bytes
pub.Send(dgram, dgram.Length, UDP_BROADCAST); // Send the disconnection message off to all clients on the network via the broadcast address
}
private void Announce_Client_Connect()
{
byte[] dgram = Encoding.ASCII.GetBytes(CLIENT_ANNOUNCE); // Encode the client connection message into an array of bytes
pub.Send(dgram, dgram.Length, UDP_BROADCAST); // Send the connection message off to all clients on the network via the broadcast address
}
private void OpenBrowse()
{ // This function allows the user to browse for a file and then sets the file path textbox with the path of the file.
OpenFileDialog fopen = new OpenFileDialog();
fopen.CheckFileExists = true; fopen.CheckPathExists = true; fopen.Filter = "WAV Files|*.wav";
fopen.ShowDialog();
filepathTB.Text = fopen.FileName;
}
private void sendwavBUT_MouseClick(object sender, MouseEventArgs e)
{
if (hostsLB.Items.Count > 0 && hostsLB.SelectedItem != null)
{
TcpClient tcpsender = new TcpClient((hostsLB.SelectedItem as IPAddress).ToString(),TCP_PORT_NUMBER); // Connect to the client
sendwavBUT.Enabled = false; filesendPB.UseWaitCursor = true;
try
{
//byte[] buf = new byte[1024]; // !! TRIAL !!
FileStream fs = new FileStream(filepathTB.Text, FileMode.Open);
int dat = 0;
while(fs.CanRead && fs.Position!=fs.Length)
{
dat = fs.ReadByte();
if (dat != -1)
{
tcpsender.GetStream().WriteByte((byte)dat);
filesendPB.Value = (int)((fs.Position / fs.Length) * 100);
}
}
fs.Close(); // Release any resources used by the file stream.
}
catch(Exception err) { MessageBox.Show(err.ToString(),"Error",MessageBoxButtons.OK,MessageBoxIcon.Error); }
MessageBox.Show("File send complete.");
tcpsender.Close(); // Release any resources used by the TCP stream and close the TCP connection.
sendwavBUT.Enabled = true; filesendPB.UseWaitCursor = false; // Re-enable the send button.
}
else if (hostsLB.Items.Count <= 0)
MessageBox.Show("There are no clients to send this file to!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
else
MessageBox.Show("You must select a client!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
static IPAddress GetLocalIP() // Has the machine report its local network IP address
{ // This code snippet has been taken from Whosebug and adapted to return an IPAddress rather than a string
IPHostEntry host;
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
if (ip.AddressFamily.ToString() == "InterNetwork")
return ip;
return null;
}
private void closeToolStripMenuItem_Click(object sender, EventArgs e)
{ Application.Exit(); }
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{ OpenBrowse(); }
private void browseBUT_MouseClick(object sender, MouseEventArgs e)
{ OpenBrowse(); }
}
}
另附一张GUI图片:
感谢您的任何意见,这个问题一直让我抓狂! :)
仅查看流 reads/writes,您似乎在这一行上有错误:
wavstream.Write(readbuf, 0, readbuf.Length); // Write WAV data to wav stream
应该是:
wavstream.Write(readbuf, 0, nbytes); // Write WAV data to wav stream
目前我正在编写一个 C# 程序来满足计算机网络 class 项目,该程序可以用任何语言编写(我选择了 C#)并且必须执行某种网络多媒体过程。它可以是点对点的或基于客户端-服务器的。
我选择将我的应用程序设为点对点。客户端使用 UDP 将其 connect/disconnect 广播到本地网络上的其他客户端,然后使用 TCP 在彼此之间发送和接收 .WAV 文件。
根据连接请求,客户端将接受 TCP 连接并开始从发送客户端读取数据。
数据全部读取完毕后,客户端就可以播放.WAV文件了。
我目前一直在尝试修复我的程序中的一个错误,该错误要求将 .WAV 文件发送两次而不是一次,以便接收方获取文件并播放它。
这导致我 运行 陷入一个我之前 运行 陷入的问题:Wave header is corrupt.
之前,我 运行 解决了这个问题,因为在播放 .WAV 文件时,我没有将流位置设置为 0。这第一次修复了它。
但是,原因现在更有趣了,因为我正在尝试修复一个不同的错误。
这次的原因是.WAV文件流中的数据被分割了。一开始,数据的第一个字节是正确的(通过使用十六进制编辑器查看我正在尝试 send/receive 的 .WAV 文件中的字节来验证)然后流中填充了 1023 个字节的 0 .之后,.WAV 文件的其余数据没有拆分。
(另一次 send/recv 试验显示第一个字节再次正确,但接下来的 1023 个字节不同步且放错了位置。接下来的 1023 个字节不是 0x00,而是来自另一段放错地方的文件。)
我不知道是什么原因造成的,并已使用 Wireshark 尝试找出问题所在。我在接收端进行了一次wireshark抓包,发现发送的第一个数据包只有一个字节的数据:0x52.
下一个数据包有 1460 字节。在 NetworkStream 中的那 1460 个字节之后没有 0x00 的拆分。
下面提供的是我的程序代码。它也可以在 Github https://github.com/cparks1/ECE369ProjB-MultimediaGUI
上找到using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Net.Sockets; // For network programming
using System.Net; // For network programming
using System.Media; // For playing .WAV files
using System.IO; // For playing .WAV files (SoundPlayer in System.Media accepts either a filepath or an IO stream.)
namespace ProjectBMultimediaGUI
{
public partial class Form1 : Form
{
private delegate void ObjectDelegate(string msg, IPEndPoint sender);
private delegate void LabelChanger(string msg);
const int PUBLISH_PORT_NUMBER = 8030; // Port number used for publish (UDP communications)
const int TCP_PORT_NUMBER = 8031; // Port number used for the rest of communications (TCP communications)
IPAddress me = GetLocalIP(); // me is the IPAddress that your machine currently owns on the local network
const string CLIENT_ANNOUNCE = "[ECE 369] Multimedia client publish"; // UDP datagram to be sent when the client is announcing itself
const string CLIENT_DISCONNECT = "[ECE 369] Multimedia client disconnect"; // UDP datagram to be sent when the client is announcing that it is disconnecting
UdpClient pub = new UdpClient(PUBLISH_PORT_NUMBER, AddressFamily.InterNetwork); // Creates a new UDP client capable of communicating on a network on port defined by const, via IPv4 addressing
IPEndPoint UDP_BROADCAST = new IPEndPoint(IPAddress.Broadcast, PUBLISH_PORT_NUMBER); // Broadcast address and port
TcpListener tlisten = new TcpListener(IPAddress.Any,TCP_PORT_NUMBER); // Sets up a listener that looks for TCP connections
TcpClient tcprecvr;
Stream wavstream = new MemoryStream(); // Initializes a memory stream that will hold .wav file data when being written to. Will be reinitialized in packet receiving functions
Timer tmr = new Timer(); // Timer used to announce client on the local network every 250 ms
SoundPlayer splayer;
bool isClosing = false; // Used to determine if program is closing
byte[] readbuf = new byte[1024];
long wavpos = 0;
public Form1()
{
InitializeComponent();
#region Timer Setup
tmr.Interval = 250;
tmr.Start();
tmr.Tick += new EventHandler(tmr_Tick);
#endregion
}
private void tmr_Tick(object sender, EventArgs e)
{
if (!isClosing)
Announce_Client_Connect(); // Announce the client is connected every 250 ms
}
private void playpauseBUT_MouseClick(object sender, MouseEventArgs e)
{
Button sbut = (sender as Button);
splayer = new SoundPlayer(wavstream);
if (sbut.ImageIndex == 0) // If the PLAY button was clicked
{ // Initiate play functions
if (wavstream.CanRead && wavstream.Length > 0)
{
splayer.Stream.Position = 0;
splayer.Play();
}
sbut.ImageIndex = 1; // Change the button to show PAUSE
}
else // If the PAUSE button was clicked
{
splayer.Stop();
sbut.ImageIndex = 0; // Change the button to show PLAY
}
}
private void Form1_Load(object sender, EventArgs e)
{
butIML.ImageSize = new Size(playpauseBUT.Size.Width-1,playpauseBUT.Size.Height-1); // This ensures the play and pause buttons are always the same size as the button they are encased in
stopBUT.Size = playpauseBUT.Size; // Ensures the stop button is the same size as the play/pause button.
stopBUT.Location = new Point(stopBUT.Location.X, playpauseBUT.Location.Y);
pub.AllowNatTraversal(false); // Disables the ability for the program to communicate with the outside world, for security purposes
try { pub.BeginReceive(new AsyncCallback(RecvPub), null); }
catch(Exception err) { MessageBox.Show("An error occurred!\n"+err.ToString()); Application.Exit(); }
tlisten.AllowNatTraversal(false);
BeginListening(); // Begins listening for attempts to connect to the client via TCP
Announce_Client_Connect();
}
private void BeginListening()
{
tlisten.Start();
tlisten.BeginAcceptTcpClient(new AsyncCallback(RecvTcp), null);
}
private void stopBUT_MouseClick(object sender, MouseEventArgs e)
{
splayer.Stop();
playpauseBUT.ImageIndex = 0; // Change the play/pause button to show PLAY
}
private void mainMS_Paint(object sender, PaintEventArgs e)
{
e.Graphics.DrawLine(new Pen(Color.Black), mainMS.Left, mainMS.Bottom-1, mainMS.Right, mainMS.Bottom-1); // Draws a border on the bottom of the main menu strip.
e.Graphics.DrawLine(new Pen(Color.Black), mainMS.Left, mainMS.Top, mainMS.Right, mainMS.Top); // Draws a border on the top of the menu strip.
}
private void RecvPub(IAsyncResult res) // Function used to handle received UDP messages
{
IPEndPoint recv = new IPEndPoint(IPAddress.Any, PUBLISH_PORT_NUMBER);
byte[] message = null;
string dmessage;
if (!isClosing)
message = pub.EndReceive(res, ref recv);
if(message != null) // If a message was received
{
ObjectDelegate del = new ObjectDelegate(HandleUDPDatagram);
dmessage = Encoding.ASCII.GetString(message);
del.Invoke(dmessage, recv);
HandleUDPDatagram(dmessage, recv);
}
if (!isClosing)
pub.BeginReceive(new AsyncCallback(RecvPub), null);
}
private void RecvTcp(IAsyncResult res)
{
LabelChanger lblchgr = new LabelChanger(dataavailable); // Used for cross thread operations on dataavailLBL
wavstream = new MemoryStream(); // Clear the wav stream, we don't want two wav files in one stream, it would cause errors.
lblchgr.Invoke("Data unavailable."); // No data available yet.
//tcprecvr = tlisten.AcceptTcpClient(); // Accept the incoming TCP connection.
tcprecvr = tlisten.EndAcceptTcpClient(res); // Create a new TCP connection with the requester
NetworkStream stream = tcprecvr.GetStream(); // Get the TCP network stream
if (stream.CanRead)
{
while (!stream.DataAvailable) ;
stream.BeginRead(readbuf, 0, readbuf.Length, new AsyncCallback(RecvTCPData), null);
}
else
{
tcprecvr.Close();
MessageBox.Show("An error has occurred. Unable to read incoming TCP stream.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error, MessageBoxDefaultButton.Button1);
}
}
private void RecvTCPData(IAsyncResult res)
{
LabelChanger lblchgr = new LabelChanger(dataavailable); // Used for cross thread operations on dataavailLBL
wavpos = 0; // Reset the WAV stream position
NetworkStream stream = tcprecvr.GetStream(); // Get the TCP data stream
int nbytes = stream.EndRead(res); // Get the number of bytes read
if (nbytes == 0) // Finished reading
{
tcprecvr.Close(); // Close the TCP connection
lblchgr.Invoke("Data available!"); // Inform the user there is a .WAV file to be played
BeginListening(); // Begin listening to connection requests again
//return;
}
else // Not finished reading, data in buffer
{
wavstream.Write(readbuf, 0, readbuf.Length); // Write WAV data to wav stream
stream.BeginRead(readbuf, 0, readbuf.Length, new AsyncCallback(RecvTCPData), null); // begin read again
}
}
private void dataavailable(string msg)
{
if(InvokeRequired)
{
LabelChanger method = new LabelChanger(dataavailable);
Invoke(method, msg);
return;
}
dataavailLBL.Text = "Data available!";
}
private void HandleUDPDatagram(string msg, IPEndPoint sender) // Used for handling UDP messages
{
if (!sender.Address.Equals(me)) // Verifies the UDP datagram received isn't from your own machine.
{ //This is done because some UDP datagrams are sent to the broadcast address, which means we receive what we've sent. We obviously don't want packets from ourselves so we block them.
if (InvokeRequired && !isClosing) // Used for handling thread magic. Please don't ask me to explain this.
{
ObjectDelegate method = new ObjectDelegate(HandleUDPDatagram);
Invoke(method, msg, sender);
return;
}
switch (msg)
{
case CLIENT_ANNOUNCE: // If we've received a client connection message
if (!hostsLB.Items.Contains(sender.Address)) // If the client is not already in the list box
hostsLB.Items.Add(sender.Address); // Add the client to the listbox of clients
break;
case CLIENT_DISCONNECT: // If we've received a client disconnection message
if (hostsLB.Items.Contains(sender.Address)) // If the client is in the listbox
hostsLB.Items.Remove(sender.Address); // Remove the client from the listbox of clients
break;
}
}
}
private void Form1_FormClosing(object sender, FormClosingEventArgs e)
{
isClosing = true;
Announce_Client_Disconnect(); // Declare your disconnection to the other clients on the network
}
private void Announce_Client_Disconnect()
{
byte[] dgram = Encoding.ASCII.GetBytes(CLIENT_DISCONNECT); // Encode the client disconnection message into an array of bytes
pub.Send(dgram, dgram.Length, UDP_BROADCAST); // Send the disconnection message off to all clients on the network via the broadcast address
}
private void Announce_Client_Connect()
{
byte[] dgram = Encoding.ASCII.GetBytes(CLIENT_ANNOUNCE); // Encode the client connection message into an array of bytes
pub.Send(dgram, dgram.Length, UDP_BROADCAST); // Send the connection message off to all clients on the network via the broadcast address
}
private void OpenBrowse()
{ // This function allows the user to browse for a file and then sets the file path textbox with the path of the file.
OpenFileDialog fopen = new OpenFileDialog();
fopen.CheckFileExists = true; fopen.CheckPathExists = true; fopen.Filter = "WAV Files|*.wav";
fopen.ShowDialog();
filepathTB.Text = fopen.FileName;
}
private void sendwavBUT_MouseClick(object sender, MouseEventArgs e)
{
if (hostsLB.Items.Count > 0 && hostsLB.SelectedItem != null)
{
TcpClient tcpsender = new TcpClient((hostsLB.SelectedItem as IPAddress).ToString(),TCP_PORT_NUMBER); // Connect to the client
sendwavBUT.Enabled = false; filesendPB.UseWaitCursor = true;
try
{
//byte[] buf = new byte[1024]; // !! TRIAL !!
FileStream fs = new FileStream(filepathTB.Text, FileMode.Open);
int dat = 0;
while(fs.CanRead && fs.Position!=fs.Length)
{
dat = fs.ReadByte();
if (dat != -1)
{
tcpsender.GetStream().WriteByte((byte)dat);
filesendPB.Value = (int)((fs.Position / fs.Length) * 100);
}
}
fs.Close(); // Release any resources used by the file stream.
}
catch(Exception err) { MessageBox.Show(err.ToString(),"Error",MessageBoxButtons.OK,MessageBoxIcon.Error); }
MessageBox.Show("File send complete.");
tcpsender.Close(); // Release any resources used by the TCP stream and close the TCP connection.
sendwavBUT.Enabled = true; filesendPB.UseWaitCursor = false; // Re-enable the send button.
}
else if (hostsLB.Items.Count <= 0)
MessageBox.Show("There are no clients to send this file to!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
else
MessageBox.Show("You must select a client!", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
}
static IPAddress GetLocalIP() // Has the machine report its local network IP address
{ // This code snippet has been taken from Whosebug and adapted to return an IPAddress rather than a string
IPHostEntry host;
host = Dns.GetHostEntry(Dns.GetHostName());
foreach (IPAddress ip in host.AddressList)
if (ip.AddressFamily.ToString() == "InterNetwork")
return ip;
return null;
}
private void closeToolStripMenuItem_Click(object sender, EventArgs e)
{ Application.Exit(); }
private void openToolStripMenuItem_Click(object sender, EventArgs e)
{ OpenBrowse(); }
private void browseBUT_MouseClick(object sender, MouseEventArgs e)
{ OpenBrowse(); }
}
}
另附一张GUI图片:
感谢您的任何意见,这个问题一直让我抓狂! :)
仅查看流 reads/writes,您似乎在这一行上有错误:
wavstream.Write(readbuf, 0, readbuf.Length); // Write WAV data to wav stream
应该是:
wavstream.Write(readbuf, 0, nbytes); // Write WAV data to wav stream