Hier eine kleine Spielerei die ich mal gemacht habe, daher eigentlich nicht ausreichend getestet, sieht auch nicht so schön aus und mir ists egal was mit dem Code angestellt wird. Das ganze wurde in C# geschireben. Es sollte lediglich zum herumspielen oder sonst was animieren. Die zwei Klassen sollten eigentlich für sich selber sprechen. Der Code wird nicht weiter erklärt ausser folgende Punkte:
Folgende Namespaces werden gebraucht:
Irgendwo in eurem Code sollte
vorhanden sein weil sonst nur standardmässig 2 Verbindungen aufgebaut werden können.
Hier sind die zwei Klassen:
Viel Spass
Folgende Namespaces werden gebraucht:
PHP Code:
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.IO;
using System.Net;
using System.Windows.Forms;
using System.Threading;
PHP Code:
System.Net.ServicePointManager.DefaultConnectionLimit = 1000;
Hier sind die zwei Klassen:
PHP Code:
class Download
{
private FileStream _file;
private string _url;
private int _countthreads;
private int _timeout;
private long _contentlength;
private List<Segment> _segmentList;
private List<Thread> _threadList;
public Download(string url, int timeout = 5000)
{
_url = url;
_timeout = timeout;
_segmentList = new List<Segment>();
_threadList = new List<Thread>();
}
public long GetFileSize()
{
long contentLength;
try
{
WebRequest req = HttpWebRequest.Create(_url);
req.Timeout = _timeout;
req.Method = "HEAD";
WebResponse resp = req.GetResponse();
contentLength = Convert.ToInt64(resp.Headers.Get("Content-Length"));
resp.Close();
return contentLength;
}
catch (Exception)
{
try
{
HttpWebRequest req = (HttpWebRequest)WebRequest.Create(_url);
req.Timeout = _timeout;
HttpWebResponse resp = (HttpWebResponse)req.GetResponse();
contentLength = resp.ContentLength;
resp.Close();
return contentLength;
}
catch (Exception)
{
return -1;
}
}
}
public void createDownload(FileStream file, long contentLength, int countthreads)
{
_countthreads = countthreads;
_file = file;
_contentlength = contentLength;
for (int i = 0; i < _countthreads; i++)
{
long segmentstart;
long segmentstop;
if (i != 0)
{
segmentstart = Convert.ToInt64(Math.Round(_contentlength / (double)(_countthreads) * (i), 0));
segmentstop = Convert.ToInt64(Math.Round(_contentlength / (double)(_countthreads) * (i + 1), 0));
segmentstart++;
}
else
{
segmentstart = 0;
segmentstop = Convert.ToInt64(Math.Round(_contentlength / (double)(_countthreads) * (i + 1), 0));
}
Segment segment = new Segment(file, _url, segmentstart, segmentstop);
segment.finished += new EventHandler(finishedSegment);
_threadList.Add(segment.prepare());
_segmentList.Add(segment);
}
for (int i = 0; i < _threadList.Count; i++)
{
_threadList[i].Start();
}
}
public FileStream createFile()
{
SaveFileDialog dialog = new SaveFileDialog();
dialog.ShowDialog();
if (dialog.FileName != "")
{
return (FileStream)dialog.OpenFile();
}
else
{
throw new Exception("Fail!");
}
}
public void finishedSegment(object seg, EventArgs args)
{
if (_segmentList.Count > 1)
{
_segmentList.Remove((Segment)seg);
}
else
{
_segmentList.Remove((Segment)seg);
_file.Close();
}
}
public List<long[]> getStats()
{
List<long[]> stats = new List<long[]>();
foreach (Segment seg in _segmentList)
{
long[] stat = seg.getStats();
stats.Add(stat);
}
return stats;
}
}
PHP Code:
class Segment
{
public event EventHandler finished;
private FileStream _fs;
private Stream _downstream;
private long _start;
private long _end;
private long _downloaded;
private int _bufferlength;
private string _url;
private Thread _loaderThread;
private HttpWebResponse _resp;
public Segment(FileStream fs, string url, long start, long end, int bufferlength = 256)
{
_fs = fs;
_start = start;
_end = end;
_downloaded = 0;
_bufferlength = bufferlength;
_url = url;
}
public Thread prepare()
{
try
{
HttpWebRequest part = (HttpWebRequest)WebRequest.Create(_url);
part.AddRange(_start);
_resp = (HttpWebResponse)part.GetResponse();
_downstream = _resp.GetResponseStream();
_loaderThread = new Thread(delegate() { doLoad(); });
return _loaderThread;
}
catch (Exception)
{
throw new Exception("Segmentierter Download konnte nicht erstellt werden!");
}
}
private void doLoad()
{
bool nextbytes = true;
byte[] buffer = new byte[_bufferlength];
int howmuchread = 0;
long pos = 0;
while ((howmuchread = _downstream.Read(buffer, 0, _bufferlength)) != 0 && nextbytes)
{
if (_end != -1)
{
if (_start + pos + howmuchread > _end)
{
howmuchread -= (int)((pos + (long)howmuchread) - (_end - _start));
nextbytes = false;
}
}
writeFile(_fs, buffer, (int)(_start + pos), howmuchread);
pos += howmuchread;
_downloaded += howmuchread;
}
_downstream.Close();
_resp.Close();
if (finished != null)
{
finished(this, new EventArgs());
}
}
public void writeFile(FileStream fs, byte[] buffer, int start, int size)
{
if (!Monitor.TryEnter(fs, 2000))
{
}
else
{
try
{
fs.Seek(start, SeekOrigin.Begin);
fs.Write(buffer, 0, size);
}
finally
{
Monitor.Exit(fs);
}
}
}
internal long[] getStats()
{
long[] stat = new long[3];
stat[0] = _start;
stat[1] = _downloaded;
stat[2] = _end;
return stat;
}
}