2010-12-08 4 views
1

J'ai une classe de serveur Java comme ceci:Socket transfère un fichier

ServerSocket servsock = new ServerSocket(63456); 
boolean read = false; 
while (!read) { 
    Socket sock = servsock.accept(); 
    int length = 1024; 
    byte[] mybytearray = new byte[length]; 
    OutputStream os = sock.getOutputStream(); 
    BufferedInputStream bis = new BufferedInputStream(new FileInputStream(myFile)); 
    while (true) { 
    int i = bis.read(mybytearray, 0, mybytearray.length); 
    if (i == 1) { 
     break; 
    } 
    os.write(mybytearray, 0, mybytearray.length); 
    os.flush(); 
    } 
    sock.close(); 
    read = true; 
} 

` Et le client est comme ceci:

Socket sock = new Socket("127.0.0.1", 63456); 
byte[] mybytearray = new byte[1024]; 
InputStream is = sock.getInputStream(); 
FileOutputStream fos = new FileOutputStream("C:/tmp/NEWtmp.rar"); 
BufferedOutputStream bos = new BufferedOutputStream(fos); 
int bytesRead = is.read(mybytearray, 0, mybytearray.length); 
while(bytesRead != -1) { 
    bos.write(mybytearray, 0, bytesRead); 
    bytesRead = is.read(mybytearray, 0, mybytearray.length); 
} 
bos.close(); 
sock.close(); 

Une question est: Pourquoi la boucle ne se limite pas à la fin du fichier? Une deuxième question serait, pourquoi est aussi si lent?

Répondre

4

Il ne s'arrête pas parce que

if (i == 1) { 

dans votre source de serveur doit être

if (i == -1) { 

Ou, si vous voulez être vraiment sûr:

if (i <= 0) { 

, vous risquez aussi corruption de données avec cette ligne:

os.write(mybytearray, 0, mybytearray.length); 

Vous devriez changer cela:

os.write(mybytearray, 0, i); 

sur la performance - déplacer l'appel à l'extérieur de la boucle whileos.flush();. Lorsque vous videz un flux réseau, vous le forcez à envoyer des données mises en mémoire tampon au réseau. Cela force la couche réseau à envoyer et à accuser réception des charges utiles TCP de 1024 octets (charges utiles Ethernet plus importantes, bien sûr), qui est probablement significativement plus petite que votre PMTU. Vous n'avez besoin de vider que lorsque vous avez fini d'envoyer des données, ou lorsque vous voulez que le client reçoive les données mises en tampon maintenant. La suppression de l'appel de vidage de chaque itération permettra au tampon réseau au niveau du système d'exploitation de faire son travail et de segmenter les données en autant de paquets que possible.

+0

Merci, ça a marché! – hephestos

2

Deuxième question - votre client lit les octets directement à partir du flux de socket brut. Utilisez les BufferedInputStream/décorateurs de BufferedOutputStream, cela devrait augmenter les performances:

côté serveur

BufferedOutputStream os = new BufferedOutputStream(sock.getOutputStream()); 

côté client

BufferedInputStream is = new BufferedInputStream(sock.getInputStream()); 

Les flux bruts ne sont pas en mémoire tampon (AFAIK) si vous avez ajouter le tampon manuellement, si nécessaire.

+0

Oui, cela a ajouté de la vitesse. C'était si simple ;-) J'aurais dû le voir moi-même, en tout cas, merci. – hephestos

Questions connexes