我编写了一个客户机/服务器应用程序来发送文件。它适用于服务器和客户端在同一台机器上,但是当我将服务器放在另一台机器上时,服务器读取套接字时出现错误。套接字通信在同一台机器上工作,但不在不同机器之间
这是服务器的代码:
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;
}
}
[这](https://stackoverflow.com/a/16001812/ 92546)的答案可能会流露出一些光芒。请注意'NetworkStream.Read'返回读取的字节数。你似乎不在乎,只是假设你会得到你想要的。当你在不同的机器上运行客户机和服务器时,它们之间会存在一个真正的网络,这些网络之间往往会分割大量的传输数据,而这些数据可能并不明显,只是在一个只是混洗缓冲区的系统上运行。 – HABO
谢谢你的回答 ,但我认为tcp协议保证发送信息 –
当你使用'netStream.Read(b,0,4);'而没有得到返回值,你怎么知道四个字节被读取? 'netStream.Read(b,0,size);'会造成更多问题。当大小超过约1500字节的典型以太网帧大小时,会出现碎片。尝试将数据包的大小限制在较小的值,例如1200字节。然后拿到一份[WireShark](https://www.wireshark.org/),看看机器之间真正的移动。 – HABO