- PR -

ファイル転送プログラムを作ったのですが、転送ができません。

1
投稿者投稿内容
にきーた
会議室デビュー日: 2006/01/25
投稿数: 5
お住まい・勤務地: 東京都
投稿日時: 2006-01-26 15:40
はじめまして、にきーたといいます。

学校でJavaを習ったので、冬休みを利用してファイルを転送するプログラムを作成してみました。
冬休み後も暇を見つけては、教科書片手にライブラリを見つつがんばったんですが、どうしてもうまく動きません。
もうかれこれ1週間以上この不具合と格闘し続けています。
どうか知恵をお貸しください。

***プログラム概説***
サーバーはマルチスレッドで複数のクライアントからの接続を受けられるようにしています。
サーバーはクライアントからの接続1つにつきCellオブジェクトをひとつ用意して管理します。
1つのCellオブジェクトは、1つのMessageHandlerオブジェクト(クライアントからのファイル要求を受ける)と複数のFileHandlerオブジェクト(ファイルを転送する)を持ちます。
クライアントは複数のFileReciverオブジェクトをもち、同時に複数のファイルをサーバーから受け取れるようにしています。

通信の流れとしては、Serverはポート2006番で接続を待ち、Clientからの接続を受けるとCellをひとつ用意してそれをCircularListに追加。
作り出されたCellはMessageHandlerをひとつ起動して、Clientからのファイル要求を待ちます。
Clientはファイル要求を出すと同時にFileRecieverをひとつ起動します。
Serverは来たアクセスが新たなClientからなのか、それとも現在通信中のClientのFileRecieverによるものなのかどうかを判別後、後者の場合は適切なCellに対し接続(ソケット)をわたします。
FileRecieverからの接続を受け取ったCellはFileHandlerを起動し、Client側のFileRecieverとServer側のFileHandlerとの間でファイル転送が始まります。
FileHandlerやFileRecieverはThreadを継承したクラスになっているので、ClientはServerから複数のファイルを同時に受け取ることができます。
またServerは複数のクライアントからの接続を受けることができます。

下に整理したソースコードを載せていますが、一応元のソースコードはこれです。
http://www004.upp.so-net.ne.jp/minimax/Transfer2.java


***症状***
Serverクラスを起動してから、Clientクラスを実行してサーバーにアクセスし、ファイル名(a.jpgなど)を入力してリターンキーを押すと、転送の途中で「java.net.SocketException: Software caused connection abort: socket write error」が出てしまい、ファイルの転送が途中で止まってしまいます。
サイズの小さいテキストファイルはきちんと転送することができましたが、バイナリファイルでは途中でとまってしまい数KBしか転送できません。
JPGデータを送ると、ファイルは形成されていますが開いてみると画像が途中で切れていて一部分しか描画されていません。

Serverクラス内のFileHandlerクラス(とよく似たもの)と、Clientクラス内のFileRecieverクラス(とよく似たもの)を使って、マルチスレッドでない転送プログラムを作るとうまく転送することができたので、ファイルの読み込みと書き込みの部分は問題ないとおもうんですが…。
そのプログラムはこれです。
http://www004.upp.so-net.ne.jp/minimax/Transfer.java


***ソースコード***
長いですが、どうかよろしくお願いします。

コード:

//サーバークラス
class Server{
//ファイル用ソケット作成(インナークラス)
class FileHandler extends Thread{
Socket incoming;
String filename;

FileHandler(Socket i,String s){
incoming=i;
filename=s;
}

public void run(){
try{
//ファイルをクライアントに転送
FileInputStream in=new FileInputStream(filename);
byte[] buff=new byte[4096];
int len;
while(true){
len=in.read(buff,0,4096);
incoming.getOutputStream().write(buff,0,len);
if(len<4096){
break;
}
}
in.close(); incoming.close();
}catch(IOException e){}
}
}

//Stringデータ用ソケット作成(インナークラス)
class MessageHandler extends Thread{
Socket incoming;
String filename;

MessageHandler(Socket i){
incoming=i;
}

public void run(){
try{
PrintWriter message=new PrintWriter(incoming.getOutputStream(),true);
BufferedReader request=new BufferedReader(new InputStreamReader(incoming.getInputStream()));

while(true){
String inputline=request.readLine();

if(inputline!=null){
if(inputline.equals("bye")){ break; }
filename=inputline;
}
}
message.close(); request.close(); incoming.close();
}catch(IOException e){}
}
}

//個々のクライアント管理用クラス(インナークラス)
class Cell{
Cell next;
String address;
MessageHandler mh;

Cell(String s){
next=null;
address=s;
}

String getAddress(){
if(mh.isAlive()){
address=mh.incoming.getInetAddress().toString();
return address;
}
else{
address="kara";
return address;
}
}

void runMessageHandler(Socket incoming){
mh=new MessageHandler(incoming);
mh.start();
}

void runFileHandler(Socket incoming){
new FileHandler(incoming, mh.filename).start();
}
}

// 循環リスト(インナークラス)
class CircularList{
Cell header;
int length;

CircularList(){
header=new Cell("**List Head**");
length=0;
}

void add(Cell x){
getCell(length).next=x;
x.next=header;
length++;
}

void remove(int n){
getCell(n-1).next=getCell(n+1);
length--;
}

Cell getCell(int n){
Cell p=header;
for(int i=0; i<n; i++){
p=p.next;
}
return p;
}
}


//Serverの記述開始
int port;
CircularList list=new CircularList();

void run(){

try{
ServerSocket server=new ServerSocket(port);

loop:
while(true){
Socket incoming=server.accept();

//アクセスが現在接続中のクライアントによるものか、新規クライアントによるものかどうか判断
for(int i=1; i<list.length; i++){
if(list.getCell(i).getAddress().equals(incoming.getInetAddress().toString())){
list.getCell(i).runFileHandler(incoming);
continue loop;
}
else if(list.getCell(i).address.equals("kara")){
list.remove(i);
}
}

list.add(new Cell(incoming.getInetAddress().toString()));
list.getCell(list.length).runMessageHandler(incoming);
}
}catch(Exception e){}
}
}


//クライアントクラス
class Client{
//ファイル受信用クラス(インナークラス)
class FileReciever extends Thread{
String host;
int port;
String filename;

FileReciever(String aHost, int aPort,String file){
host=aHost;
port=aPort;
filename=file;
}

public void run(){
try{
Socket socket=new Socket(host,port);
PrintWriter pw=new PrintWriter(socket.getOutputStream(),true);

pw.println(filename);

//サーバーからのデータ受信
FileOutputStream out=new FileOutputStream(filename);
byte[] buff=new byte[4096];
int len;

while(true){
len=socket.getInputStream().read(buff,0,4096);
out.write(buff,0,len);
if(len<4096){
break;
}
}
out.close(); socket.close();
}catch(IOException e){}
}
}

//Clientの記述開始
String host;
int port;
String filename;

void run(){
try{
Socket socket=new Socket(host,port);

//キーボードからの入力(サーバーへの回答用)
BufferedReader infK=new BufferedReader(new InputStreamReader(System.in));
PrintWriter pw=new PrintWriter(socket.getOutputStream(),true);
BufferedReader br=new BufferedReader(new InputStreamReader(socket.getInputStream()));

while(true){
filename=infK.readLine();

if(filename!=null){
if(filename.equals("bye")){
pw.println("bye");
break;
}
pw.println(filename);
new FileReciever(host,port,filename).start();
}
}
br.close(); infK.close(); pw.close(); socket.close();
}catch(IOException e){}
}
}




[ メッセージ編集済み 編集者: にきーた 編集日時 2006-01-26 15:40 ]
1

スキルアップ/キャリアアップ(JOB@IT)