不完整的头与套接字c#
本文关键字:套接字 | 更新日期: 2023-09-27 18:14:57
嗨,我试着发送和http请求到一个广播流网站,然后读取响应,我有这两个源,一个是主要的(我用wpf测试过),另一个是小的套接字的助手…好吧,所有的工作,与localhost和其他网站但是当我尝试发送请求到"209.9.238.6:6042"时,响应的头永远不会完整但被截断。
我已经做了很多测试,但没有它只适用于Thread.sleep(200);在发送和接收之间看(1),所以看起来listen()来得太早了只下载了一部分…
你能帮我吗?
c
public partial class MainWindow : Window
{
public MainWindow()
{
InitializeComponent();
}
private void connectionButton_Click(object sender, RoutedEventArgs e)
{
var url = "209.9.238.6:6042";
var sockHelp = new SocketHelper(url);
sockHelp.onConnect += sockHelp_onConnect;
sockHelp.connect();
}
void testDebug(string str) {
Action action = () => debugTxt.Text = str;
Dispatcher.BeginInvoke(action);
}
void sockHelp_onConnect(object sender, SocketHelperEventArgs e)
{
var sockHelp = sender as SocketHelper;
testDebug("Connected");
var header = "";
header+="GET / HTTP/1.0'r'n";
header+="Accept: */*'r'n";
header+="Host: 209.9.238.6'r'n";
header+="Connection: close'r'n'r'n";
sockHelp.onSend += sockHelp_onSend;
sockHelp.sendAsync(Encoding.UTF8.GetBytes(header));
}
private void sockHelp_onSend(object sender, SocketAsyncEventArgs e)
{
var sockHelp = sender as SocketHelper;
sockHelp.onReceive+=sockHelp_onReceive;
//Thread.Sleep(200); (1) uncomment this line... to make works
sockHelp.listen();
}
void sockHelp_onReceive(object sender, SocketAsyncEventArgs arg_)
{
testDebug("Receiving");
var t = Encoding.UTF8.GetString(arg_.Buffer);
var idx = IndexOf(arg_.Buffer, new byte[] { 0x0d, 0x0a, 0x0d, 0x0a });
if (idx < 0)
{
testDebug(Encoding.UTF8.GetString(arg_.Buffer));
return ;
}
byte[] binBuff = new byte[idx + 1];
System.Buffer.BlockCopy(arg_.Buffer, 0, binBuff, 0, idx + 1);
testDebug(Encoding.UTF8.GetString(binBuff));
}
private int IndexOf(byte[] searchIn, byte[] searchFor)
{
if ((searchIn != null) && (searchIn != null))
{
if (searchFor.Length > searchIn.Length) return 0;
for (int i = 0; i < searchIn.Length; i++)
{
int startIndex = i;
bool match = true;
for (int j = 0; j < searchFor.Length; j++)
{
if (searchIn[startIndex] != searchFor[j])
{
match = false;
break;
}
else if (startIndex < searchIn.Length)
{
startIndex++;
}
}
if (match)
return startIndex - searchFor.Length;
}
}
return -1;
}
}
}
helper.cs
namespace TestSocket
{
/// <summary>
/// </summary>
public class SocketHelperEventArgs : EventArgs
{
public SocketHelperEventArgs(SocketError se)
{
socketError = se;
}
public SocketHelperEventArgs() { }
SocketError socketError;
SocketAsyncEventArgs args;
}
public class SocketHelper
{
byte[] _buffer = new byte[1024*2];
SocketAsyncEventArgs _args = new SocketAsyncEventArgs();
readonly Socket _socket;
public event EventHandler<SocketHelperEventArgs> onError;
public event EventHandler<SocketHelperEventArgs> onConnect;
public event EventHandler<SocketAsyncEventArgs> onReceive;
public event EventHandler<SocketAsyncEventArgs> onSend;
public SocketHelper(string url)
{
int port=0;
string[] addressVector = url.Split(':');
if (addressVector.Length == 1)
port = 80;
else
port = int.Parse(addressVector[1]);
_args.RemoteEndPoint = new DnsEndPoint(addressVector[0], port); ;
_args.Completed += SocketAsyncEventArgs_Completed;
_socket = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
}
public void listen()
{
_args.SetBuffer(_buffer, 0, _buffer.Length);
_socket.ReceiveAsync(_args);
}
public void connect()
{
bool completesAsynchronously = _socket.ConnectAsync(_args);
if (!completesAsynchronously)
{
SocketAsyncEventArgs_Completed(_args.ConnectSocket, _args);
}
}
public void sendAsync(byte[] data) {
_args.SetBuffer(data, 0, data.Length);
_socket.SendAsync(_args);
}
private void SocketAsyncEventArgs_Completed(object sender, SocketAsyncEventArgs e)
{
// check for errors
if (e.SocketError != SocketError.Success)
{
if (onError != null) onError(this, new SocketHelperEventArgs(e.SocketError));
CleanUp(e);
return;
}
switch (e.LastOperation)
{
case SocketAsyncOperation.Connect:
if (onConnect != null) onConnect(this, EventArgs.Empty as SocketHelperEventArgs);
break;
case SocketAsyncOperation.Send:
if (onSend!= null) onSend(this, e);
break;
case SocketAsyncOperation.Receive:
if (onReceive != null) onReceive(this,e);
break;
}
}
private void CleanUp(SocketAsyncEventArgs e)
{
if (e.ConnectSocket != null)
{
e.ConnectSocket.Shutdown(SocketShutdown.Both);
e.ConnectSocket.Close();
}
}
}
}
您似乎认为您将在一次阅读中获得整个响应。这是不对的。当数据可用时,您将从套接字获得一些数据。您需要根据应用程序级协议(HTTP或ICY或您正在使用的任何协议)检测是否有更多的数据,如果有,则重新武装异步读取。
现在你正在消耗套接字接收缓冲区中发生的任何内容。等待似乎是有效的,因为在该超时之后会有更多的数据堆积在那里,但不能保证您将获得所有内容。