Simple server/client - can't get it to work

EDN Admin

Well-known member
Joined
Aug 7, 2010
Messages
12,794
Location
In the Machine
What I am trying to do is essentially an easy server/client architecture. Client connects to server, server enumerates all files on the hard drive and sends that list back to the client.<br/>
Unfortunately, I cant get it to work properly. Ive managed to narrow it down to the fact that the client receives incorrect/faulty data from the socket (see debug lot the program produces).<br/>
If anyone could help me debug it, Id appreciate it.
Feel free to point out improvements, of course, should there be any.
Here is the source for the server:<br/>

<pre class="prettyprint using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.Net;
using System.IO;
using System.Threading;
using System.IO.Compression;
using MiscUtil.IO;

namespace C2C_Transfer_Server
{
public partial class Form1 : Form
{
CircularBuffer.QueueCB m_Buffer = new CircularBuffer.QueueCB(1 * 1000 * 1000);
//bool m_Run = true;
ManualResetEvent m_SessionStartedEvent = new ManualResetEvent(false);
ManualResetEvent m_SessionFinishedEvent = new ManualResetEvent(false);
ManualResetEvent m_SendingFinishedEvent = new ManualResetEvent(false);
const int MsgFilename = 0;
const int MsgServerFinished = 1;
const int MsgClientFinished = 2;

private int OutstandingWrites = 0;

static bool IsSet(FileAttributes Attributes, FileAttributes SetAttribute)
{
return ((Attributes & SetAttribute) == SetAttribute);
}

public Form1()
{
InitializeComponent();
}

void EncodeAndWrite(Stream Target, Stream From)
{
From.Position = 0;
using (var Writer = new StreamWriter(new NonClosingStreamWrapper(Target)))
{
for (int i = 0; i < From.Length; i++)
{
int b = From.ReadByte();
Writer.Write(b);
Writer.Write(.);
}
}
Target.Flush();
}

private void SendingThread(NetworkStream Stream)
{
var Encoder = new UTF8Encoding();
m_SessionStartedEvent.WaitOne(); // Waits until server is ready to send data

using (var FilenameStream = new MemoryStream())
using (var BinarySocket = new BinaryWriter(Stream))
using (var DebugFile = new FileStream("A:\ServerDebug.txt", FileMode.Create))
using (var FileStream = new StreamWriter(DebugFile))
{
FileStream.WriteLine("");
FileStream.Flush();

bool Run = true;
while (Run)
{
int NumItems;
FilenameStream.Position = 0;
FilenameStream.SetLength(0);
lock (m_Buffer)
{
NumItems = m_Buffer.Count;
using (var MemoryBufStreamWriter = new StreamWriter(
new NonClosingStreamWrapper(FilenameStream)))
using (var MemoryBufBinaryWriter = new BinaryWriter(
new NonClosingStreamWrapper(FilenameStream)))
{
while (m_Buffer.Count > 0)
{
String item = (String)m_Buffer.Dequeue();
MemoryBufStreamWriter.WriteLine(item);
}
}
}

using (var CompressedStream = new MemoryStream())
{
FilenameStream.Position = 0;
using (var Compressor = new GZipStream(CompressedStream, CompressionMode.Compress, true))
FilenameStream.CopyTo(Compressor);

FileStream.WriteLine("---BEGIN---");
FileStream.WriteLine("Num items: " + NumItems);
FileStream.WriteLine("Compressed data length: " + CompressedStream.Length);
FileStream.Write("Compressed data: ");
FileStream.Flush();
CompressedStream.Position = 0;
EncodeAndWrite(DebugFile, CompressedStream);
FileStream.WriteLine("nUncompressed data length: " + FilenameStream.Length);
FileStream.Flush();
FilenameStream.Position = 0;
FilenameStream.CopyTo(DebugFile);
DebugFile.Flush();

BinarySocket.Write(MsgFilename);
BinarySocket.Write(NumItems);
BinarySocket.Write(CompressedStream.Length);
BinarySocket.Flush();
CompressedStream.Position = 0;
CompressedStream.CopyTo(Stream);
//Stream.Flush();
//BinarySocket.Write(CompressedStream.GetBuffer(), 0, (int)CompressedStream.Length);
}

// Wait until there is data to send
bool DataAvailable = false;
while (!DataAvailable)
{
lock (m_Buffer)
DataAvailable = (m_Buffer.Count > 0);
if (m_SessionFinishedEvent.WaitOne(0) && !DataAvailable)
{
BinarySocket.Write(MsgServerFinished);
using (var ClientSocket = new BinaryReader(Stream))
{
int Msg = ClientSocket.ReadInt32();
System.Diagnostics.Debug.Assert(Msg == MsgClientFinished);
}
Run = false;
break;
}
}
}
}

// If set, server has finished sending client data
m_SendingFinishedEvent.Set();
}

private void Form1_Load(object sender, EventArgs e)
{
var Listener = new TcpListener(System.Net.IPAddress.Any, 9999);
Listener.Start();
using (var Socket = Listener.AcceptTcpClient())
using (var Stream = Socket.GetStream())
{
new System.Threading.Thread(delegate() { SendingThread(Stream); }).Start();
WalkDirectoryTree(new System.IO.DirectoryInfo("C:\"));
m_SessionFinishedEvent.Set();
m_SendingFinishedEvent.WaitOne(); // Wait until all data has been sent to client
}
this.Close();
}

void WalkDirectoryTree(System.IO.DirectoryInfo root)
{
try
{
if (IsSet(root.Attributes, System.IO.FileAttributes.ReparsePoint))
return;

System.IO.FileInfo[] files = null;
System.IO.DirectoryInfo[] subDirs = null;

// First, process all the files directly under this folder
try
{
files = root.GetFiles("*.*");
}
// This is thrown if even one of the files requires permissions greater
// than the application provides.
catch (UnauthorizedAccessException e)
{
// This code just writes out the message and continues to recurse.
// You may decide to do something different here. For example, you
// can try to elevate your privileges and access the file again.
Console.WriteLine(e.Message);
}
catch (System.IO.DirectoryNotFoundException e)
{
Console.WriteLine(e.Message);
}
catch (System.IO.PathTooLongException)
{
Console.WriteLine(root.FullName);
}

if (files != null)
{
try
{
foreach (System.IO.FileInfo fi in files)
{
// In this example, we only access the existing FileInfo object. If we
// want to open, delete or modify the file, then
// a try-catch block is required here to handle the case
// where the file has been deleted since the call to TraverseTree().
bool TryAgain = true;
while (TryAgain)
{
try
{
lock (m_Buffer)
{
TryAgain = false;
m_Buffer.Enqueue(fi.FullName);
}
}
catch (IndexOutOfRangeException)
{
// Buffer full; try again later.
Thread.Sleep(100);
TryAgain = true;
}
}
m_SessionStartedEvent.Set();
OutstandingWrites++;
}
}
catch (System.IO.PathTooLongException)
{
Console.WriteLine(root.FullName);
}

// Now find all the subdirectories under this directory.
subDirs = root.GetDirectories();

foreach (System.IO.DirectoryInfo dirInfo in subDirs)
{
// Resursive call for each subdirectory.
WalkDirectoryTree(dirInfo);
}
}
}
catch (Exception e)
{
Console.WriteLine(e.Message);
}
}
}
}[/code]
And here is for the client:<br/>

<pre class="prettyprint using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Net.Sockets;
using System.IO.Compression;
using System.IO;
using System.Diagnostics;
using MiscUtil.IO;

namespace C2C_Transfer_Client
{
public partial class Form1 : Form
{
const int MsgFilename = 0;
const int MsgServerFinished = 1;
const int MsgClientFinished = 2;

public Form1()
{
InitializeComponent();
}

void EncodeAndWrite(Stream Target, Stream From)
{
From.Position = 0;
using (var Writer = new StreamWriter(new NonClosingStreamWrapper(Target)))
{
for (int i = 0; i < From.Length; i++)
{
int b = From.ReadByte();
Writer.Write(b);
Writer.Write(.);
}
}
Target.Flush();
}

private void Form1_Load(object sender, EventArgs e)
{
var Socket = new TcpClient("localhost", 9999);
var Stream = Socket.GetStream();
var Decoder = new UTF8Encoding();

bool Run = true;

using (var File = new FileStream("C:\test.txt", FileMode.Create))
using (var FileBufStream = new BufferedStream(File, 1 * 1024 * 1024))
using (var FileStream = new StreamWriter(FileBufStream))
using (var BinarySocket = new BinaryReader(Stream))
using (var StreamSocket = new StreamReader(Stream))
using (var DebugFile = new FileStream("A:\ClientDebug.txt", FileMode.Create))
using (var DebugFileStream = new StreamWriter(DebugFile))
{
while (Run)
{
int Msg = BinarySocket.ReadInt32();
switch (Msg)
{
case MsgFilename:
int NumItems = BinarySocket.ReadInt32();
long CompressedDataLength = BinarySocket.ReadInt64();
DebugFileStream.WriteLine("---BEGIN---");
DebugFileStream.WriteLine("Num items: " + NumItems);
DebugFileStream.WriteLine("Compressed data length: " + CompressedDataLength);

// Read data
int ReadBytes = 0;
byte[] CompressedBuffer = new byte[CompressedDataLength];
while (ReadBytes < CompressedBuffer.Length)
ReadBytes += BinarySocket.Read(CompressedBuffer, 0, CompressedBuffer.Length);

DebugFileStream.Write("Compressed data: ");
DebugFileStream.Flush();
EncodeAndWrite(DebugFile, new MemoryStream(CompressedBuffer));

// Decompress data
var CompressedStream = new MemoryStream(CompressedBuffer, false);
var UncompressedStream = new MemoryStream();
using (var Uncompressor = new GZipStream(CompressedStream,
CompressionMode.Decompress, true))
{
Uncompressor.CopyTo(UncompressedStream);
}

DebugFileStream.WriteLine("nUncompressed data length: " + UncompressedStream.Length);
DebugFileStream.Flush();
UncompressedStream.Position = 0;
using (var BinaryReader = new BinaryReader(UncompressedStream))
using (var StreamReader = new StreamReader(UncompressedStream))
{
for (int i = 0; i < NumItems; i++)
{
String Filename = StreamReader.ReadLine();
DebugFileStream.WriteLine(Filename);
DebugFileStream.Flush();
FileStream.WriteLine(Filename);
}
FileStream.WriteLine("");
FileStream.Flush();
}
break;
case MsgServerFinished:
using (var ServerSocket = new BinaryWriter(Stream))
{
ServerSocket.Write(MsgClientFinished);
}
Run = false;
break;
}
}
}
this.Close();
}
}
}[/code]
<br/>

<br/>

View the full article
 
Back
Top