C# Winsock接收数据
我正在尝试向服务器发送一个非常大的信息,大小为11000,但我遇到了一个问题。信息不完整 查看代码: 在我的服务器上,有一个循环C# Winsock接收数据,c#,winsock,C#,Winsock,我正在尝试向服务器发送一个非常大的信息,大小为11000,但我遇到了一个问题。信息不完整 查看代码: 在我的服务器上,有一个循环 do { Tick = Environment.TickCount; Listen.AcceptClient(); Listen.Update(); } 听。更新 public static void UpdateClient(UserConnection client) {
do
{
Tick = Environment.TickCount;
Listen.AcceptClient();
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;
}
这是我的winsock服务器
有人有建议或解决方案吗?从这里开始:。它将解释一些您需要知道的事情,包括您不太可能在一次调用中读取已发送的所有数据。每个TCP程序都需要包含通过某种类型的循环接收数据的逻辑,在大多数情况下,还需要包含解释接收数据的逻辑,以识别接收数据的各个元素之间的边界,例如逻辑消息,等等……唯一的例外是当应用程序协议规定从连接到关闭的整个传输代表单个单元时,在这种情况下,唯一重要的边界是流的结尾
除了在这里包含的一小段代码中解决许多错误之外:
不要使用TcpClient.Available;在正确的代码中不需要它。
不要使用Marshal.GetExceptionCode检索托管异常的异常信息
当您的值已经是System.Int32的实例时,不要使用Convert.ToInt32。更一般地说,在一个简单的cast可以完成同样的事情的场景中,即使这里不需要cast,也不要使用Convert,但是我可以从这里的代码看出你的一般习惯是什么……你应该改掉这个习惯。
不要忽略例外情况。要么做一些实际处理它们的事情,要么让它们向上传播调用堆栈。如果Read方法引发了异常,那么UpdateClient方法中的其余代码将无法工作,但是您还是继续执行它。
不要对NetworkStream对象使用Flush方法。它什么都不做,只是因为Stream类需要它。
请使用Stream.ReadAsync,而不是为每个连接指定一个线程
通过包含异常类型和接受异常对象引用的变量来捕获异常
请使用持久解码器对象对UTF8编码的文本或任何其他可变字节长度的文本编码进行解码,这样,如果字符的编码表示跨越多个接收缓冲区,则文本仍能正确解码。
最后:
不要发帖。如果一个问题没有包含一个合适的、完整的代码示例,那么很难精确地回答这个问题。
增编:
不要使用goto语句。使用适当的回路,例如,在运行时。如果使用了正确的循环,您可能会避免代码中无法分支回实际读取调用的错误。
不要期望Read方法填充您传递给它的缓冲区。正如我前面提到的,不仅不能保证发送的所有数据都会在一次Read调用中返回,而且也不能保证在Read返回之前,您传递给Read的整个缓冲区都会被填满。
不要一次读取一个字节。这是消除性能和/或引入bug的最可靠的方法之一。以你自己为例,我看不出有什么明显的错误——在查找更多数据时,您只打算读取单个字节,然后打算返回到更大的缓冲区中读取数据——但这并不是必需的,只是正常地尝试读取更多数据……这样您就可以获得相同的信息,而代码中没有可能导致错误的特殊情况,并且在任何情况下都可以使代码更难理解。
一定要看一下网络代码的其他示例和教程。重新发明轮子可能最终会带来一个好的解决方案,但这种可能性很低,而且与遵循其他人的好榜样相比,它更耗时,更容易出错。
我重申:请阅读Winsock常见问题解答。它有很多有价值的信息,每个想要编写网络代码的人都需要知道
我还要重申:如果没有代码示例,您无法得到准确的答案。谢谢您的提示,但我的问题仍然存在……问题已编辑。
//Tem alguém querendo entrar na putaria? ;D
if (listener.Pending())
{
//Adicionamos ele na lista
Clients.Add(new UserConnection(listener.AcceptTcpClient(), Clients.Count()));