【发布时间】:2017-05-27 22:36:31
【问题描述】:
我编写了一个客户端/服务器应用程序来发送文件。如果服务器和客户端在同一台机器上,它可以工作,但是当我将服务器放在另一台机器上时,服务器读取套接字时会出错。
这是服务器的代码:
class conexion
{
int sizeofonpacket = 9999;
string filsc="";
string titre = "";
bool sendfilcomand = false;
int conteur1 = 0;
int conteur2 = 0;
BinaryWriter sf;
TcpListener listiner;
TcpClient client;
NetworkStream netStream;
public conexion(IPAddress ip, int port)
{
listiner = new TcpListener(ip, port);
listiner.Start();
client = listiner.AcceptTcpClient();
netStream = client.GetStream();
Console.Write("client is present \r\n ");
}
public void read()
{
while (client.Connected)
{
string returndata;
int size = 0;
string c = "";
byte[] bs = new byte[4];
byte[] b = new byte[1];
try
{
//read the comand of client "s" for string or "b" for binary file if it is "s" it read the string that client write
//if it is "b" we read the string "dfgjsdgfjdsgfjhdsgfj" it is not important
Console.Write("ready \r\n ");
netStream.Read(b, 0, 1);
c = Encoding.UTF8.GetString(b);
Console.WriteLine("\r\n comand :" + c);
b = new byte[4];
netStream.Read(b, 0, 4);
returndata = Encoding.UTF8.GetString(b);
size = Int32.Parse(returndata);
Console.WriteLine("\r\n size de packet int =" + size);
b = new byte[size];
netStream.Read(b, 0, size);
}
catch
{
Console.WriteLine("\r\n conexion echoue");
listiner.Stop();
}
switch (c)
{
case "b":
if (sendfilcomand == false) //if sendfilcomand is false we read first the title
{
sendfilcomand = true;
break;
}
sendfilcomand = false;
filsc = titre;
Console.WriteLine("\r\nle titr est:" + titre);
titre = "";
sf = new BinaryWriter(new FileStream(filsc, FileMode.Create));
conteur2 = 0;
conteur1 = size;
crebfile(b);
Console.WriteLine("\r\n creat file for " + conteur2 + " to " + conteur1);
b = new byte[sizeofonpacket];
while (size != 0)
{
try
{
netStream.Read(bs, 0, 4);
returndata = Encoding.UTF8.GetString(bs);
size = Int32.Parse(returndata);
conteur1 = size;
Console.WriteLine("sizee a get" + size);
if (size == 0)
{
Console.WriteLine("yout est termine");
sf.Close();
conteur1 = 0;
conteur2 = 0;
break;
}
else if (size != sizeofonpacket)
{
b = new byte[size];
}
netStream.Read(b, 0, size);
}
catch
{
Console.WriteLine("\r\n imposible to read ");
}
crebfile(b);
b.Initialize();
}
sf.Close();
conteur1 = 0;
conteur2 = 0;
break;
case "s":
returndata = Encoding.UTF8.GetString(b);
Console.WriteLine("\r\n" + returndata);
if (sendfilcomand)
{
titre = returndata;
Console.WriteLine("titre a get" + titre);
break;
}
break;
default:
Console.WriteLine("\r\n rien comand");
break;
}
}
}
public string quadripl(string s)
{
while (s.Length < 4)
{
s = "0" + s;
}
return s;
}
public void crebfile(byte[] byts)
{
try
{
sf.Write(byts, 0, conteur1);
}
catch
{
Console.WriteLine("imposible de crer le fichier");
}
}
}
这是客户端代码:
class conexion
{
string filsr;
int sizeofonpacket = 9999;
bool sendfilcomand = false;
bool getfilcomand = false;
int bali;
int fali;
Stream file;
TcpListener listiner;
TcpClient client;
NetworkStream netStream;
public conexion(string ip, int port)
{
listiner = null;
Console.Write("star client ");
client = new TcpClient(ip, 3568);
netStream = client.GetStream();
}
public void send()
{
while (client.Connected)
{
//enter the comand "s" or "b"
string c = "";
Console.WriteLine("\r\n ecrir comand:");
c = Console.ReadLine();
string s = "";
if (c == "s")
{
Console.WriteLine("\r\n entrer string:");
s = Console.ReadLine();
}
string size = "";
Byte[] sendBytes = null;
//try
{
switch (c)
{
case "b":
Console.WriteLine("\r\n comand binary file");
netStream.Write(Encoding.UTF8.GetBytes(c), 0, 1);
if (sendfilcomand == false) //we will first send the patsh of file after we will send data of file
{
sendBytes = Encoding.UTF8.GetBytes("dfgjsdgfjdsgfjhdsgfj"); //this is not important
size = quadripl(sendBytes.Length.ToString());
netStream.Write(Encoding.UTF8.GetBytes(size), 0, Encoding.UTF8.GetBytes(size).Length);
netStream.Write(sendBytes, 0, sendBytes.Length);
sendfilcomand = true;
s = getitr();
c = "s";
goto case "s";
}
sendfilcomand = false; //now we will send data
filsr = actitr(); //the title is save in "C:/Users/Ce-Pc/Desktop/titreactuel.txt"
file = new FileStream(filsr, FileMode.Open);
fali = (int)file.Length;
bali = 0;
byte[] bs = new byte[4];
Console.WriteLine("\r\n star sending ");
do
{
sendBytes = filebtobyte(filsr); //read part of file to send
Console.WriteLine("\r\n terminer " + bali + " " + " " + fali);
size = quadripl(sendBytes.Length.ToString()); //just for add the zero
Console.WriteLine("\r\n le size de fichier binair est " + size);
netStream.Write(Encoding.UTF8.GetBytes(size), 0, Encoding.UTF8.GetBytes(size).Length);
netStream.Write(sendBytes, 0, sendBytes.Length);
} while (bali != -1); //when we come to last part of the file (filebtobyte give -1 to bali)
bali = 0;
size = quadripl("0");
Console.WriteLine("\r\n terminer fiiiiiiiiiiiiiiiiiiiiiiiiiiiiiiin ");
netStream.Write(Encoding.UTF8.GetBytes(size), 0, Encoding.UTF8.GetBytes(size).Length);
netStream.Read(bs, 0, 4);
break;
case "s":
Console.WriteLine("\r\n comand string");
netStream.Write(Encoding.UTF8.GetBytes(c), 0, 1);
size = quadripl(s.Length.ToString());
sendBytes = Encoding.UTF8.GetBytes(size);
Console.WriteLine("\r\n size=" + size);
netStream.Write(sendBytes, 0, sendBytes.Length);
sendBytes = Encoding.UTF8.GetBytes(s);
netStream.Write(sendBytes, 0, sendBytes.Length);
if (sendfilcomand)
{
c = "b";
goto case "b";
}
break;
default:
Console.WriteLine("\r\n rien comand");
break;
}
}
catch
{
Console.WriteLine("\r\n imposible de transfer");
}
}
Console.Write("client est deconect \r\n ");
}
//////////////////the functions//////////////////////////////////
public byte[] filebtobyte(string s)
{
byte[] byts = null;
try
{
if (fali - bali < sizeofonpacket)
{
byts = new byte[fali - bali];
file.Read(byts, 0, fali - bali);
file.Close();
bali = -1;
}
else
{
byts = new byte[sizeofonpacket];
file.Read(byts, 0, sizeofonpacket);
bali += sizeofonpacket;
}
}
catch
{
Console.WriteLine("imposible de trouver le fichier");
}
return byts;
}
public string quadripl(string s)
{
while (s.Length < 4)
{ s = "0" + s; }
return s;
}
public string getitr()
{
StreamReader titrfil = new StreamReader("C:/Users/Ce-Pc/Desktop/titre.txt");
string sss = "";
try
{
sss = titrfil.ReadLine();
Console.WriteLine("\r\n le chemin " + sss);
titrfil.Close();
}
catch
{
Console.WriteLine("\r\n imposible");
}
return sss;
}
public string actitr()
{
StreamReader titrfil = new StreamReader("C:/Users/Ce-Pc/Desktop/titreactuel.txt");
string sss = "";
try
{
sss = titrfil.ReadLine();
Console.WriteLine("\r\n le chemin " + sss);
titrfil.Close();
}
catch
{
Console.WriteLine("\r\n imposible");
}
return sss;
}
}
【问题讨论】:
-
This 答案可能会有所启发。请注意,
NetworkStream.Read返回读取的字节数。你似乎不在乎,只是假设你会得到你想要的。当您在不同的机器上运行客户端和服务器时,它们之间会存在一个真实的网络,这往往会导致大型传输碎片化,这在一个仅对缓冲区进行洗牌的单个系统上运行可能并不明显。 -
谢谢你的回答,但我认为 tcp 协议保证发送信息
-
当你使用
netStream.Read(b, 0, 4);没有得到返回值时,你怎么知道读取了四个字节?这对于netStream.Read(b, 0, size);变得更加成问题。当大小超过大约 1500 字节的典型以太网帧大小时,就会出现碎片。尝试将数据包的大小限制为更小的东西,例如1200 字节。然后获取WireShark 的副本,看看机器之间的真正移动。 -
我尝试使用等于 1400 的大小但不成功,他在循环的某个步骤中发送了错误数据
标签: c#