我正在尝试向服务器发送一个非常大的信息(大小为11000)并且遇到问题。信息未完整。
查看代码:
在我的服务器上,有一个循环。
do
{
Tick = Environment.TickCount;
Listen.AcceptClient();
Listen.Update();
}
Listen.update
public static void UpdateClient(UserConnection client)
{
string data = null;
Decoder utf8Decoder = Encoding.UTF8.GetDecoder();
// byte[] buffer = new byte[client.TCPClient.Available];
//try
//{
//client.TCPClient.GetStream().
// client.TCPClient.GetStream().Read(buffer, 0, buffer.Length);
//}
//catch
//{
// int code = System.Runtime.InteropServices.Marshal.GetExceptionCode();
// Console.WriteLine("Erro Num: " + code);
//}
//data = Encoding.UTF8.GetString(buffer);
//Console.WriteLine("Byte is: " + ReadFully(client.TCPClient.GetStream(), 0));
Console.WriteLine("Iniciando");
byte[] buffer = ReadFully(client.TCPClient.GetStream(), 0);
int charCount = utf8Decoder.GetCharCount(buffer, 0, buffer.Length);
Char[] chars = new Char[charCount];
int charsDecodedCount = utf8Decoder.GetChars(buffer, 0, buffer.Length, chars, 0);
foreach (Char c in chars)
{
data = data + String.Format("{0}", c);
}
int buffersize = buffer.Length;
Console.WriteLine("Byte is: " + buffer.Length);
Console.WriteLine("Data is: " + data);
Console.WriteLine("Size is: " + data.Length);
Server.Network.ReceiveData.SelectPacket(client.Index, data);
}
/// <summary>
/// Reads data from a stream until the end is reached. The
/// data is returned as a byte array. An IOException is
/// thrown if any of the underlying IO calls fail.
/// </summary>
/// <param name="stream">The stream to read data from</param>
/// <param name="initialLength">The initial buffer length</param>
public static byte[] ReadFully(Stream stream, int initialLength)
{
// If we've been passed an unhelpful initial length, just
// use 32K.
if (initialLength < 1)
{
initialLength = 32768;
}
byte[] buffer = new byte[initialLength];
int read = 0;
int chunk;
chunk = stream.Read(buffer, read, buffer.Length - read);
checkreach:
read += chunk;
// If we've reached the end of our buffer, check to see if there's
// any more information
if (read == buffer.Length)
{
int nextByte = stream.ReadByte();
// End of stream? If so, we're done
if (nextByte == -1)
{
return buffer;
}
// Nope. Resize the buffer, put in the byte we've just
// read, and continue
byte[] newBuffer = new byte[buffer.Length * 2];
Array.Copy(buffer, newBuffer, buffer.Length);
newBuffer[read] = (byte)nextByte;
buffer = newBuffer;
read++;
goto checkreach;
}
// Buffer is now too big. Shrink it.
byte[] ret = new byte[read];
Array.Copy(buffer, ret, read);
return ret;
}
Listen.AcceptClient
//Tem alguém querendo entrar na putaria? ;D
if (listener.Pending())
{
//Adicionamos ele na lista
Clients.Add(new UserConnection(listener.AcceptTcpClient(), Clients.Count()));
这是我的winsock服务器。
任何人都有提示或解决方案吗?
答案 0 :(得分:0)
从这里开始:Winsock FAQ。它将解释您需要了解的一些事项,包括您不可能通过一次调用Read()
来读取已发送的所有数据。每个单独的TCP程序都需要包含通过某种类型的循环接收数据的某个逻辑,并且在大多数情况下还需要逻辑来解释所接收的数据以识别所接收数据的各个元素之间的边界(例如逻辑消息等......唯一的例外是当应用程序协议规定从连接到闭包的整个传输代表一个“单元”时,在这种情况下唯一重要的边界是流的结尾。)
另外(为了解决这里包含的一小部分代码中的一些错误):
TcpClient.Available
; 正确的代码中不需要它。Marshal.GetExceptionCode()
检索托管例外的异常信息Convert.ToInt32()
的实例时,System.Int32
。更一般地说,在简单的强制转换完成同样的事情的情况下,根本不要使用Convert
(即使这里不需要演员,但我可以从代码中看出你的一般习惯是什么......你应该打破这种习惯。)UpdateClient()
方法抛出异常,则Read()
方法中的其余代码无法正常工作,但无论如何都要继续执行。Flush()
对象上使用NetworkStream
方法。它什么都不做(只有因为Stream
类需要它才有效)。Stream.ReadAsync()
而不是将线程专用于每个连接Decoder
对象来解码UTF8编码的文本(或任何其他可变字节长度的文本编码),以便字符的编码表示跨越多个接收的缓冲区,文本仍然正确解码。最后:
的附录:强>
goto
声明。使用适当的循环(例如while
)。如果您使用了正确的循环,您可能已经避免了代码中的错误,即您无法回到实际的Read()
调用。Read()
方法填充您传递的缓冲区。不仅(正如我上面已经提到的)不能保证所有发送的数据都会在一次调用中返回Read()
,因此无法保证传递给Read()
的整个缓冲区都将在Read()
返回之前填写。我将重申:请阅读Winsock常见问题解答。它有很多有价值的信息,每个想要编写网络代码的人都需要知道。
我还要重申:没有COMPLETE代码示例,你无法得到准确的答案。