Sockets in C#: How to get the response stream? - c#

I'm trying to replace this:
void ProcessRequest(object listenerContext)
{
var context = (HttpListenerContext)listenerContext;
Uri URL = new Uri(context.Request.RawUrl);
HttpWebRequest.DefaultWebProxy = null;
HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create(URL);
httpWebRequest.Method = context.Request.HttpMethod;
httpWebRequest.Headers.Clear();
if (context.Request.UserAgent != null) httpWebRequest.UserAgent = context.Request.UserAgent;
foreach (string headerKey in context.Request.Headers.AllKeys)
{
try { httpWebRequest.Headers.Set(headerKey, context.Request.Headers[headerKey]); }
catch (Exception) { }
}
using (HttpWebResponse httpWebResponse = (HttpWebResponse)httpWebRequest.GetResponse())
{
Stream responseStream = httpWebResponse.GetResponseStream();
if (httpWebResponse.ContentEncoding.ToLower().Contains("gzip"))
responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
else if (httpWebResponse.ContentEncoding.ToLower().Contains("deflate"))
responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);
MemoryStream memStream = new MemoryStream();
byte[] respBuffer = new byte[4096];
try
{
int bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
while (bytesRead > 0)
{
memStream.Write(respBuffer, 0, bytesRead);
bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
}
}
finally
{
responseStream.Close();
}
byte[] msg = memStream.ToArray();
context.Response.ContentLength64 = msg.Length;
using (Stream strOut = context.Response.OutputStream)
{
strOut.Write(msg, 0, msg.Length);
}
}
catch (Exception ex)
{
// Some error handling
}
}
with sockets. This is what I have so far:
void ProcessRequest(object listenerContext)
{
HttpListenerContext context = (HttpListenerContext)listenerContext;
Uri URL = new Uri(context.Request.RawUrl);
string getString = string.Format("GET {0} HTTP/1.1\r\nHost: {1}\r\nAccept-Encoding: gzip\r\n\r\n",
context.Request.Url.PathAndQuery,
context.Request.UserHostName);
Socket socket = null;
string[] hostAndPort;
if (context.Request.UserHostName.Contains(":"))
{
hostAndPort = context.Request.UserHostName.Split(':');
}
else
{
hostAndPort = new string[] { context.Request.UserHostName, "80" };
}
IPHostEntry ipAddress = Dns.GetHostEntry(hostAndPort[0]);
IPEndPoint ip = new IPEndPoint(IPAddress.Parse(ipAddress.AddressList[0].ToString()), int.Parse(hostAndPort[1]));
socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp);
socket.Connect(ip);
BEGIN NEW CODE
Encoding ASCII = Encoding.ASCII;
Byte[] byteGetString = ASCII.GetBytes(getString);
Byte[] receiveByte = new Byte[256];
string response = string.Empty;
socket.Send(byteGetString, byteGetString.Length, 0);
Int32 bytes = socket.Receive(receiveByte, receiveByte.Length, 0);
response += ASCII.GetString(receiveByte, 0, bytes);
while (bytes > 0)
{
bytes = socket.Receive(receiveByte, receiveByte.Length, 0);
strPage = strPage + ASCII.GetString(receiveByte, 0, bytes);
}
socket.Close();
string separator = "\r\n\r\n";
string header = strPage.Substring(0,strPage.IndexOf(separator));
string content = strPage.Remove(0, strPage.IndexOf(separator) + 4);
byte[] byteResponse = ASCII.GetBytes(content);
context.Response.ContentLength64 = byteResponse .Length;
context.Response.OutputStream.Write(byteResponse , 0, byteResponse .Length);
context.Response.OutputStream.Close();
END NEW CODE
After connecting to the socket I don't know how to get the Stream response to decompress, and send back to context.Response.OutputStream
Any help will be appreciated.
Thanks.
Cheers.
EDIT 2:
With this edit now seems to be working fine (same as HttpWebRequest at least). Do you find any error here?
EDIT 3:
False alarm... Still can't get this working
EDIT 4:
I needed to add the following lines to Scott's code ... because not always the first to bytes of reponseStream are the gzip magic number.
The sequence seems to be: 0x0a (10), 0x1f (31), 0x8b (139). The last two are the gzip magic number. The first number was always before in my tests.
if (contentEncoding.Equals("gzip"))
{
int magicNumber = 0;
while (magicNumber != 10)
magicNumber = responseStream.ReadByte();
responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
}

Here's some code that works for me.
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.IO.Compression;
namespace HttpUsingSockets {
public class Program {
private static readonly Encoding DefaultEncoding = Encoding.ASCII;
private static readonly byte[] LineTerminator = new byte[] { 13, 10 };
public static void Main(string[] args) {
var host = "stackoverflow.com";
var url = "/questions/523930/sockets-in-c-how-to-get-the-response-stream";
IPHostEntry ipAddress = Dns.GetHostEntry(host);
var ip = new IPEndPoint(ipAddress.AddressList[0], 80);
using (var socket = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp)) {
socket.Connect(ip);
using (var n = new NetworkStream(socket)) {
SendRequest(n, new[] {"GET " + url + " HTTP/1.1", "Host: " + host, "Connection: Close", "Accept-Encoding: gzip"});
var headers = new Dictionary<string, string>();
while (true) {
var line = ReadLine(n);
if (line.Length == 0) {
break;
}
int index = line.IndexOf(':');
headers.Add(line.Substring(0, index), line.Substring(index + 2));
}
string contentEncoding;
if (headers.TryGetValue("Content-Encoding", out contentEncoding)) {
Stream responseStream = n;
if (contentEncoding.Equals("gzip")) {
responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
}
else if (contentEncoding.Equals("deflate")) {
responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);
}
var memStream = new MemoryStream();
var respBuffer = new byte[4096];
try {
int bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
while (bytesRead > 0) {
memStream.Write(respBuffer, 0, bytesRead);
bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
}
}
finally {
responseStream.Close();
}
var body = DefaultEncoding.GetString(memStream.ToArray());
Console.WriteLine(body);
}
else {
while (true) {
var line = ReadLine(n);
if (line == null) {
break;
}
Console.WriteLine(line);
}
}
}
}
}
static void SendRequest(Stream stream, IEnumerable<string> request) {
foreach (var r in request) {
var data = DefaultEncoding.GetBytes(r);
stream.Write(data, 0, data.Length);
stream.Write(LineTerminator, 0, 2);
}
stream.Write(LineTerminator, 0, 2);
// Eat response
var response = ReadLine(stream);
}
static string ReadLine(Stream stream) {
var lineBuffer = new List<byte>();
while (true) {
int b = stream.ReadByte();
if (b == -1) {
return null;
}
if (b == 10) {
break;
}
if (b != 13) {
lineBuffer.Add((byte)b);
}
}
return DefaultEncoding.GetString(lineBuffer.ToArray());
}
}
}
You could substitute this for the Socket/NetworkStream and save a bit of work.
using (var client = new TcpClient(host, 80)) {
using (var n = client.GetStream()) {
}
}

Socket, by definition, is the low level to access the network. You can even use datagram protocols with a socket. In that case a stream does not make sense at all.
While I'm not sure why are you doing what HttpWebRequest easily accomplishes, to read/write data to a socket, you use the Send/Receive methods. If you want to have a stream like access to a TCP socket, you should use the TcpClient/TcpListener classes which wrap a socket and provide a network stream for it.

There's also the NetworkStream class that takes a Socket as a parameter. ;)

Related

C# Multi threaded Server

I have this client and server code.
Client:
namespace ClientTest
{
internal class Program
{
private static TcpClient client;
private static NetworkStream stream;
private static void Main(string[] args)
{
string temp;
client = new TcpClient("192.168.1.2",5052);
stream = client.GetStream();
Console.WriteLine(client.SendBufferSize);
while ((temp = Console.ReadLine()) != "exit")
{
Send(temp);
}
Thread one=new Thread(()=> SendFile(new FileInfo(#"1.doc")));
one.Start();
Thread two=new Thread(()=> SendFile(new FileInfo(#"2.docx")));
two.Start();
// Console.ReadKey(true);
}
public static void SendFile(FileInfo file)
{
stream = client.GetStream();
byte[] id = BitConverter.GetBytes((ushort)1);
byte[] size = BitConverter.GetBytes(file.Length);
byte[] fileName = Encoding.UTF8.GetBytes(file.Name);
byte[] fileNameLength = BitConverter.GetBytes((ushort)fileName.Length);
byte[] fileInfo = new byte[12 + fileName.Length];
id.CopyTo(fileInfo, 0);
size.CopyTo(fileInfo, 2);
fileNameLength.CopyTo(fileInfo, 10);
fileName.CopyTo(fileInfo, 12);
stream.Write(fileInfo, 0, fileInfo.Length); //Размер файла, имя
byte[] buffer = new byte[1024 * 32];
int count;
long sended = 0;
using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open))
while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, count);
sended += count;
Console.WriteLine("{0} bytes sended.", sended);
}
stream.Flush();
}
private static void Send(string message)
{
byte[] id = BitConverter.GetBytes((ushort)0);
byte[] msg = Encoding.UTF8.GetBytes(message);
byte[] msgLength = BitConverter.GetBytes((ushort)msg.Length);
byte[] fileInfo = new byte[12 + msg.Length];
id.CopyTo(fileInfo, 0);
msgLength.CopyTo(fileInfo, 10);
msg.CopyTo(fileInfo, 12);
stream.Write(fileInfo, 0, fileInfo.Length);
stream.Flush();
}
}
}
Server:
namespace Server_Test
{
class Server
{
static void Main(string[] args)
{
Server serv = new Server();
}
private TcpListener listener { get; set; }
private NetworkStream stream { get; set; }
public Server()
{
listener = new TcpListener(IPAddress.Parse("192.168.1.2"), 5052);
listener.Start();
new Thread(ListenForClients).Start();
}
private void ListenForClients()
{
while (true)
{
TcpClient client = this.listener.AcceptTcpClient();
new Thread(HandleClient).Start(client);
}
}
private void HandleClient(object tcpClient)
{
TcpClient client = (TcpClient)tcpClient;
while (client.Connected)
{
Recieve(client);
}
}
private void Recieve(TcpClient client)
{
byte[] buffer = new byte[client.ReceiveBufferSize];
try
{
stream = client.GetStream();
int bytesRead = stream.Read(buffer, 0, 12);
if (bytesRead == 0) return;
ushort id = BitConverter.ToUInt16(buffer, 0);
long len = BitConverter.ToInt64(buffer, 2);
ushort nameLen = BitConverter.ToUInt16(buffer, 10);
stream.Read(buffer, 0, nameLen);
string fileName = Encoding.UTF8.GetString(buffer, 0, nameLen);
if (id == 1)
{
using (BinaryWriter writer = new BinaryWriter(new FileStream(fileName, FileMode.Create)))
{
int recieved = 0;
while (recieved < len)
{
bytesRead = stream.Read(buffer, 0, client.ReceiveBufferSize);
recieved += bytesRead;
writer.Write(buffer, 0, bytesRead);
Console.WriteLine("{0} bytes recieved.", recieved);
}
}
Console.WriteLine("File length: {0}", len);
Console.WriteLine("File Name: {0}", fileName);
Console.WriteLine("Recieved!");
}
else
{
Console.WriteLine(fileName);
}
}
catch (Exception ex)
{
stream.Close();
client.Close();
Console.WriteLine(ex);
}
finally
{
stream.Flush();
}
}
}
}
The problem:i can't send 2 files in threads. If i send 1 file, server receives it and correctly saves.
What changes needed in this code to let client transfer 2 or more files and to let server receive it?
UDP. Added modified SendFile, but in doesn't work.
public static void SendFile(FileInfo file)
{
TcpClient client;
NetworkStream stream;
client = new TcpClient("192.168.1.2", 5052);
stream = client.GetStream();
byte[] id = BitConverter.GetBytes((ushort)1);
byte[] size = BitConverter.GetBytes(file.Length);
byte[] fileName = Encoding.UTF8.GetBytes(file.Name);
byte[] fileNameLength = BitConverter.GetBytes((ushort)fileName.Length);
byte[] fileInfo = new byte[12 + fileName.Length];
id.CopyTo(fileInfo, 0);
size.CopyTo(fileInfo, 2);
fileNameLength.CopyTo(fileInfo, 10);
fileName.CopyTo(fileInfo, 12);
stream.Write(fileInfo, 0, fileInfo.Length); //Размер файла, имя
byte[] buffer = new byte[1024 * 32];
int count;
long sended = 0;
using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open))
while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, count);
sended += count;
Console.WriteLine("{0} bytes sended.", sended);
}
}
On the client side, your two separate sending threads cannot share the same instance of client = new TcpClient("192.168.1.2",5052); to simultaneously send data. Each thread should have its own instance. Note, however, that it is fine for 2 client sockets to hit the same server-side IP:port simultaneously. It is just that the outbound port on the client-side has to be different between the 2 connections. When you create an additional outbound TCP connection on the client, the TcpClient will automatically use the next available outbound port.
For example, you could try something like the following:
internal class Program
{
private static void Main(string[] args)
{
SenderThreadClass stc1 = SenderThreadClass("192.168.1.2", 5052);
SenderThreadClass stc2 = SenderThreadClass("192.168.1.2", 5052);
Thread one = new Thread(()=> stc1.SendFile(new FileInfo(#"1.doc")));
one.Start();
Thread two = new Thread(()=> stc2.SendFile(new FileInfo(#"2.docx")));
two.Start();
}
}
public class SenderThreadClass
{
private TcpClient client;
private NetworkStream stream;
public SenderThreadClass(string serverIP, int serverPort)
{
client = new TcpClient(serverIP, serverPort);
stream = client.GetStream();
}
public void SendFile(FileInfo file)
{
byte[] id = BitConverter.GetBytes((ushort)1);
byte[] size = BitConverter.GetBytes(file.Length);
byte[] fileName = Encoding.UTF8.GetBytes(file.Name);
byte[] fileNameLength = BitConverter.GetBytes((ushort)fileName.Length);
byte[] fileInfo = new byte[12 + fileName.Length];
id.CopyTo(fileInfo, 0);
size.CopyTo(fileInfo, 2);
fileNameLength.CopyTo(fileInfo, 10);
fileName.CopyTo(fileInfo, 12);
stream.Write(fileInfo, 0, fileInfo.Length); //Размер файла, имя
byte[] buffer = new byte[1024 * 32];
int count;
long sended = 0;
using (FileStream fileStream = new FileStream(file.FullName, FileMode.Open))
while ((count = fileStream.Read(buffer, 0, buffer.Length)) > 0)
{
stream.Write(buffer, 0, count);
sended += count;
Console.WriteLine("{0} bytes sended.", sended);
}
stream.Flush();
}
}

Sockets: Only one usage of each socket address is normally permitted

I want to reuse a socket after I used it once, but I always get subj exception.
I found multiple questions with same issue but no working solution. I tried using code, i tried manual closing - but without any success
A little sample
using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
namespace SocketTest
{
class Program
{
static void Main()
{
for (int i = 1; i <= 2; i++)
{
var encoding = new UTF8Encoding(false);
var host = Dns.GetHostEntry("localhost");
var endpoint = new IPEndPoint(host.AddressList[0], 11322);
Console.WriteLine("Iteration #{0}\tEnpdoint = {1}", i, endpoint);
try
{
var client = new TcpClient(endpoint);
const string message = "Hello world!";
byte[] data = encoding.GetBytes(message);
client.Connect(endpoint);
var stream = client.GetStream();
stream.Write(data, 0, data.Length);
Console.WriteLine("Sent: {0}", message);
byte[] receiveData = new byte[4096];
int totalBytes = 0;
while (true)
{
int bytesRead = stream.Read(receiveData, 0, receiveData.Length);
totalBytes += bytesRead;
if (bytesRead < receiveData.Length)
break;
Array.Resize(ref receiveData, 2 * receiveData.Length);
}
var response = encoding.GetString(receiveData, 0, totalBytes);
Console.WriteLine("Received: {0}", response);
client.Client.Shutdown(SocketShutdown.Both);
client.Client.Disconnect(true);
stream.Close();
client.Close();
}
catch (Exception ex)
{
Console.WriteLine(ex.ToString());
}
Console.WriteLine();
}
}
}
}

A simple web server to consume a POST request - Server hangs after one or two requests

I am building a small windows application to consume a POST request. The code below works fine for GET requests and for the first POST request. Basically when I read the POST DATA it works fine the first time (or the first few times). After a while (a few seconds - it hangs. Any incoming request hangs. Any ideas? Assume the content length is correct.
while (true)
{
System.Console.WriteLine("The server is running at port 8001...");
System.Console.WriteLine("Waiting for a connection.....");
TcpClient client = _listener.AcceptTcpClient();
int incomingDataLength = client.ReceiveBufferSize;
Stream ist = client.GetStream();
BufferedStream bst = new BufferedStream(ist);
int k = 0;
String line = ReadLine(bst);
System.Console.WriteLine(line);
while ((line = ReadLine(bst)) != null)
{
if (line == "") break;
System.Console.WriteLine(line);
}
MemoryStream ms = new MemoryStream();
int contentLen = 3429;
//if (this.HttpHeaders.ContainsKey("Content-Length"))
{
//content_len = Convert.ToInt32(this.HttpHeaders["Content-Length"]);
byte[] buf = new byte[4096];
int to_read = content_len;
while (to_read > 0)
{
int numread = bst.Read(buf, 0, Math.Min(buf.Length, to_read));
if (numread == 0)
{
if (to_read == 0) break;
else throw new Exception("client disconnected during post");
}
to_read -= numread;
ms.Write(buf, 0, numread);
}
ms.Seek(0, SeekOrigin.Begin);
}
using (StreamReader sr = new StreamReader(ms))
{
System.Console.WriteLine(sr.ReadToEnd());
}
bst.Close();
client.Close();
And the ReadLine is
private String ReadLine(Stream stream)
{
int k;
StringBuilder lineBuilder = new StringBuilder();
while (true)
{
k = stream.ReadByte();
if (k < 0) continue;
char c = Convert.ToChar(k);
if (c == '\n') break;
if (c == '\r') continue;
lineBuilder.Append(c);
}
return lineBuilder.ToString();
}
As Yannis suggested, you may not be disposing your objects, especially your streams. Using statements, like you did with the StreamReader, will automatically do this for you. For example:
while (true)
{
System.Console.WriteLine("The server is running at port 8001...");
System.Console.WriteLine("Waiting for a connection.....");
using (TcpClient client = _listener.AcceptTcpClient())
{
int incomingDataLength = client.ReceiveBufferSize;
using (Stream ist = client.GetStream())
{
//Stream ist = client.GetStream();
using (BufferedStream bst = new BufferedStream(ist))
{
//BufferedStream bst = new BufferedStream(ist);
int k = 0;
String line = ReadLine(bst);
System.Console.WriteLine(line);
while ((line = ReadLine(bst)) != null)
{
if (line == "") break;
System.Console.WriteLine(line);
}
using (MemoryStream ms = new MemoryStream())
{
//MemoryStream ms = new MemoryStream();
int contentLen = 3429;
if (this.HttpHeaders.ContainsKey("Content-Length"))
{
//content_len = Convert.ToInt32(this.HttpHeaders["Content-Length"]);
byte[] buf = new byte[4096];
int to_read = content_len;
while (to_read > 0)
{
int numread = bst.Read(buf, 0, Math.Min(buf.Length, to_read));
if (numread == 0)
{
if (to_read == 0) break;
else throw new Exception("client disconnected during post");
}
to_read -= numread;
ms.Write(buf, 0, numread);
}
ms.Seek(0, SeekOrigin.Begin);
}
using (StreamReader sr = new StreamReader(ms))
{
System.Console.WriteLine(sr.ReadToEnd());
}
//bst.Close();
client.Close();
} //end memorystream
} //end bufferedsteam
} //end stream
} //end tcpClient
} //end while

GZipStream, how correctly read from GZipStream

I have some code writen by me in C#
string host = new Uri(_url).Host;
IPHostEntry ipAddress = Dns.GetHostEntry(host);
IPEndPoint ip = new IPEndPoint(ipAddress.AddressList[0], 80);
using (Socket s = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
s.Connect(ip);
using (NetworkStream n = new NetworkStream(s))
{
byte[] write = encoding.GetBytes(HttpQuery);
n.Write(write, 0, write.Length);
ReadLine(n);
Dictionary<string, string> headers = new Dictionary<string, string>();
while (true)
{
string line = ReadLine(n);
if (line.Length == 0)
{
break;
}
int index = line.IndexOf(':');
if (!headers.ContainsKey(line.Substring(0, index)))
{
headers.Add(line.Substring(0, index), line.Substring(index + 2));
}
}
string contentEncoding;
if (headers.TryGetValue("Content-Encoding", out contentEncoding))
{
Stream responseStream = n;
if (contentEncoding.Equals("gzip"))
{
responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
responseStream.Flush();
}
else if (contentEncoding.Equals("deflate"))
{
responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);
}
MemoryStream memStream = new MemoryStream();
byte[] respBuffer = new byte[4096];
try
{
int bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
//int bytesRead = responseStream.ReadByte();
while (bytesRead > 0)
{
memStream.Write(respBuffer, 0, bytesRead);
bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
}
}
finally
{
responseStream.Close();
}
string str = encoding.GetString(memStream.ToArray());
Then I Have an exception InvalidDataException in this line int bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
GZip header magic number is not correct.
string ReadLine(Stream stream)
{
List<byte> lineBuffer = new List<byte>();
try
{
while (true)
{
int b = stream.ReadByte();
if (b == -1)
return null;
if (b == 10)
break;
if (b != 13)
lineBuffer.Add((byte) b);
}
}
catch (Exception)
{
}
return encoding.GetString(lineBuffer.ToArray());
}
Any ideas?
Your ReadLine function returns as soon as it reads one line feed character when reading a blank line. Doesn't that potentially leave the stream positioned at a carriage return character instead of at the beginning of the GZip data stream?
in general, I found something on the subject, here's Sockets in C#: How to get the response stream? link, there is some information that before the string (s) to do so:
Stream responseStream = n;
int magicNumber = 0;
while (magicNumber != 10)
{
magicNumber = responseStream.ReadByte();
}
if (contentEncoding.Equals("gzip"))
{
responseStream = new GZipStream(responseStream, CompressionMode.Decompress);
}
perhaps I did not quite do it correctly?
nobugz
I have very succeful code writen with WttWebRequest and HttpWebResponse, BUT my page have codepape-1251, and HttpWebRequest convert url from 1251 encoding to UTF-8 I and nothing can do with this, maybe you have any ideas?
For example I have url as http://myurl.php?name=Мастер%20Создатель
HttpWebRequest convert this in http://myurl.php?name=%d0%9c%d0%b0%d1%81%d1%82%d0%b5%d1%80+%d0%a1%d0%be%d0%b7%d0%b4%d0%b0%d1%82%d0%b5%d0%bb%d1%8c (UTF-8)
BUT will be http://myurl.php?name=%CC%E0%F1%F2%E5%F0%20%D1%EE%E7%E4%E0%F2%E5%EB%FC(windows-1251), I don't know how fix this

Sockets in Visual C#. Need Help!

I'm from the Urkraine, and have bad english, but anyway not sure if there is an answer on my question.
I took example from [here][1] but i have exception that GZip magical number is not valid, why ?
public long WriteUrl()
{
long num1 = 0;
bool saveItAtCache = false;
bool existsAtCache = false;
byte[] cachedFile = null;
string ext = Path.GetExtension(_url).ToLower();
if (!_url.Contains(".php") && ".gif.jpg.swf.js.css.png.html".IndexOf(ext) != -1 && ext != "")
{
saveItAtCache = true;
cachedFile = cache.GetFile(_url);
existsAtCache = (cachedFile != null);
}
if (existsAtCache)
{
writeSuccess(cachedFile.Length, null);
socket.Send(cachedFile);
}
string host = new Uri(_url).Host;
IPHostEntry ipAddress = Dns.GetHostEntry(host);
IPEndPoint ip = new IPEndPoint(ipAddress.AddressList[0], 80);
using (Socket s = new Socket(ip.AddressFamily, SocketType.Stream, ProtocolType.Tcp))
{
s.Connect(ip);
using (NetworkStream n = new NetworkStream(s))
{
if (HttpRequestType == "GET")
{
SendRequest(n, new[] { socketQuery});
}
Dictionary<string, string> headers = new Dictionary<string, string>();
while (true)
{
string line = ReadLine(n);
if (line.Length == 0)
{
break;
}
int index = line.IndexOf(':');
if (!headers.ContainsKey(line.Substring(0, index)))
{
headers.Add(line.Substring(0, index), line.Substring(index + 2));
}
}
string contentEncoding;
if (headers.TryGetValue("Content-Encoding", out contentEncoding))
{
Stream responseStream = n;
if (contentEncoding.Equals("gzip"))
{
responseStream = new GZipStream(responseStream, CompressionMode.Decompress, true);
}
else if (contentEncoding.Equals("deflate"))
{
responseStream = new DeflateStream(responseStream, CompressionMode.Decompress);
}
var memStream = new MemoryStream();
var respBuffer = new byte[4096];
try
{
int bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
//int bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
while (bytesRead > 0)
{
memStream.Write(respBuffer, 0, bytesRead);
bytesRead = responseStream.Read(respBuffer, 0, respBuffer.Length);
}
}
finally
{
responseStream.Close();
}
string str = encoding.GetString(memStream.ToArray());
ManageCookies(headers["Set-Cookie"], _headers["Host"]);
cachedFile = encoding.GetBytes(str);
if (saveItAtCache)
{
cache.Store(_url, cachedFile);
}
writeSuccess(cachedFile.Length, headers["Set-Cookie"]);
socket.Send(cachedFile);
num1 = str.Length;
}
else
{
while (true)
{
string line = ReadLine(n);
if (line == null)
{
break;
}
num1 = line.Length;
}
}
}
}
return num1;
}
In these lines
string str = encoding.GetString(memStream.ToArray());
ManageCookies(headers["Set-Cookie"], _headers["Host"]);
cachedFile = encoding.GetBytes(str);
You're converting the byte array to a string and then back to a byte array. Since the original data is a gzip or jpg or whatever and not really a string, this conversion is probably screwing it up. I don't see you using str at all, so just take it out (use cachedFile.Length when you need the length instead of str.Length).

Categories