자바 소켓 프로그래밍 파일전송 질문입니다.

kyy0810의 이미지

한곳에 모으니 드럽게 기네요;;;

채팅프로그램인데 파일전송이랑 채팅이랑 같이 되는걸 구현하려고하는데요.
채팅은 잘되는 파일전송부분에서 파일 하나보내고 소켓닫는거는 잘 되는데
파일을 계속해서 보내고 싶은데 클라이언트에서는 계속보내는데 서버에서 파일 한번 받고
그것도 크기가 0바이트로 나오고 다음에 보내는 파일을 받아들이질 못하네요.
부탁드립니다. ㅠㅠ

////// server측 /////////

채팅 관련



import java.io.*;
import java.net.*;
import java.util.*;
public class ChatS {

public static void main(String args[]){
System.out.println("자바 커뮤니티 채팅 서버 v1.0");

ServerSocket ss = null;
Vector v =null;

try {
//9000번 포트를 사용하는 서버 소켓을 생성한다.
ss = new ServerSocket(9000);
v = new Vector(10);

while(true){
//클라이언트로부터 접속 요청이 발생하면 서버와 클라이언트
// 사이에 새로운 소켓을 생성한다.
Socket c = ss.accept();

// accept() 메소드가 한번 실행된이후로
// 새로운 소켓이 올때까지 대기하므로 아래 문장도 accept()가 실행될때까지 기다린다.



//클라이언트의 정보를 저장하는 ClientInfo 클래스를 생성하고
// 벡터 객체를 저장한다.
ClientInfo ci = new ClientInfo(c);
v.add(ci); // 새로운 클라이언트가 접속할때마다 벡터에 저장한다.

//각 소켓(클라이언트 하나당 소켓 하나 생성)에 대한 작업을 수행할 쓰레드를 생성한다.
ChatThread ct = new ChatThread(c,v);
Thread t = new Thread(ct);
t.start();

System.out.println(ci.getIP() +"가 접속했습니다.");

}
}catch(Exception e){

try{
// 서버 소켓에 예외가 발생하면 소켓을 닫고 프로그램을 종료한다.
ss.close();
System.exit(0);

}catch(Exception ie){

}
}

}

}
import java.io.*;
import java.net.*;
import java.util.*;

public class ChatThread implements Runnable {

private Socket c = null;
private BufferedReader br = null;
private Vector v = null;
private File file;
private InputStream is;
public ChatThread(Socket c, Vector v){
this.c = c;
this.v = v;

// 클라이언트로부터 전송된 내용을 읽어오기 위한 입력 스트림을 생성한다.
try{
InputStream is = c.getInputStream();
br = new BufferedReader ( new InputStreamReader(is));

} catch (Exception e){

}

}
public void run(){
while(true){
String str = null;
int j =0;
try{
// 클라이언트로부터 문자열을 읽어온다.
// 클라이언트로부터 파일을 읽어온다.
str = br.readLine();


}catch(Exception e){
break;
}

for(int i = 0 ; i // 읽어온 문자열을 백터객체에 저장된 각 클라이언트에 전송한다.
ClientInfo ci = (ClientInfo)v.get(i);
ci.write(str); // ClientInfo 클래스의 write 메소드 사용
}
}

try{
//예외가 발생하여 while
// 루프가 종료되면 스트림과 소켓을 닫는다.

br.close();
c.close();
} catch(Exception e) {


}
}
}

import java.io.*;
import java.net.*;
import java.util.*;

public class ClientInfo { // 서버에서 클라이언트 정보를 가져와서 저장한다.

private Socket c;
private String ip;
private BufferedWriter bw;

public ClientInfo(Socket c){

this.c = c;


// 소켓을 연결한 클라이언트의
// 아이피 정보를 저장한다.
ip = c.getInetAddress().getHostAddress();


//
// 클라이언트에 문자열을 전송하기 위한 출력 스트림을 생성한다.
try{
bw = new BufferedWriter (new OutputStreamWriter(c.getOutputStream()));

} catch (Exception e){

}
}
public boolean write(String str){

// 인자로 받은 문자열을 출력 스트림을 사용하여 전송한다.


try{

bw.write(str+"\n");
bw.flush();
}catch(Exception e) {
return false;
}
return true;
}


public String getIP(){
return ip;
}
}



// 파일 관련//




import java.io.*;
import java.net.*;
import java.util.*;



public class FileS {
public static void main(String[] args) {
ServerSocket ss = null;
Socket c =null;
//클라이언트와 연결된 소켓들을 배열처럼 저장할 벡터객체 생성
Vector v =null;
try{
ss= new ServerSocket(9401);
v = new Vector(10);
while(true){
System.out.println("파일전송 접속대기중..");
c = ss.accept();
//클라이언트와 연결된 소켓을 벡터에 담기

ClientInfo ci = new ClientInfo(c);
v.add(ci);

FileThread ct = new FileThread(c,v);
Thread t = new Thread(ct);
t.start();

System.out.println(ci.getIP() +"가 접속했습니다.");

}
}catch(IOException ie){
System.out.println(ie.getMessage());
}
}
}


import java.io.*;
import java.net.*;
import java.util.*;

import javax.swing.JOptionPane;

public class FileThread implements Runnable {

private Socket c = null;
private BufferedReader br = null;
private Vector v = null;
private File file;
private String fileName=null;
private FileOutputStream out;
private InputStream ins=null;
public FileThread(Socket c, Vector v){
this.c = c;
this.v = v;

// 클라이언트로부터 전송된 내용을 읽어오기 위한 입력 스트림을 생성한다.
try{

ins =c.getInputStream();
this.br = new BufferedReader ( new InputStreamReader(ins));

} catch (Exception e){

}

}
public void run(){
getFileInfo();
}
synchronized void getFileInfo(){



try{
// 클라이언트로부터 파일을 읽어온다.
fileName = br.readLine();
//int check = JOptionPane.showConfirmDialog(null,"파일을 수신하시겠습니까?","파일 전송 요청",JOptionPane.YES_NO_OPTION,JOptionPane.QUESTION_MESSAGE);
int size = Integer.parseInt(br.readLine());
System.out.println(size);
//if(check== 0){

System.out.println(file);
file= new File("c:\\3DP\\Net",fileName);

// 기록한 파일 연결함
out = new FileOutputStream(file);

// 보내온 파일의 끝까지 읽어서 파일로 씀
int temp =0;
byte[] buffer = new byte[1024];
for(int i=0; i
temp =ins.read(buffer);
if(temp==-1)
break;
System.out.println(buffer);
System.out.println(temp);
out.write(buffer);


}
file =null;
br=null; ins =null; out =null; c=null;
/*while((temp = ins.read(buffer))!=-1){
System.out.println(buffer);
//System.out.println(buffer);
out.write(buffer);

} */

//}

}catch(Exception ioe){
ioe.printStackTrace();

System.out.println("Server ReSource Clear");
try{br.close(); } catch(Exception e){ e.printStackTrace();}
try{ins.close(); } catch(Exception e){ e.printStackTrace();}
try{out.close(); } catch(Exception e){ e.printStackTrace();}

}

/* for(int i = 0 ; i // 읽어온 문자열을 백터객체에 저장된 각 클라이언트에 전송한다.
ClientInfo ci = (ClientInfo)v.get(i);

//
ci.write(str); // ClientInfo 클래스의 write 메소드 사용

*/

}

}



///////////////////////////////////////////////////////////

//////// 클라이언트 ///////////

package Client;
import java.io.*;
import java.net.*;

public class ChatClient {

private Socket s = null;
private Socket sf = null;
private String ip = null;
private int port = 0;
private int portf =0;
private String name = null;

public static void main(String args[]){
ChatClient cc = new ChatClient();
cc.init(); // 초기화

}
public ChatClient(){

}
public void init(){
//채팅클라이언트 초기화
//서버의 주소와 포트 번호를 입력받는 다이얼로그

InputForm sif = new InputForm(this);
sif.setModal(true); // 현재 창이 종료되기전까지는 다음창을 실행못함.
sif.setVisible(true);
//sif.show(true);

// 채팅에서 사용할 이름을 입력받는 다이얼로그
NameInputform nif = new NameInputform(this);
nif.setModal(true);
nif.setVisible(true);


// 입력된 서버의 주소와 포트번호로 소켓을 생성한다.

try{
s = new Socket(ip ,port);
sf = new Socket("localhost" ,portf);

} catch(Exception e){

}
// 생성된 소켓과 채팅에서 사용할 이름을 인자로 새로운
// 채팅창 프레임을 생성한다.

ChatClientForm ccf = new ChatClientForm(s,sf,name);
ccf.setVisible(true);
//ccf.show(true);
}
//초기화 값을 멤버 벼수에 저장하는 set 메서드
public void setIp(String ip){
this.ip = ip;
}
public void setPort(int port){
this.port = port;
}
public void setPortf(int portf){
this.portf = portf;
}
public void setName(String name){
this.name = name;
}
}







package Client;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;

//import sds.FileListenThread;

import java.awt.*;
import java.awt.event.*;
import java.io.*;
import java.net.*;
import java.util.Vector;

public class ChatClientForm extends JFrame implements ActionListener {

private Socket s;
private Socket sf;
private String name;


private BufferedWriter bw,bw1;
private DataInputStream dis;
private DataOutputStream dos;
private FileInputStream fis = null;
private OutputStreamWriter osw = null;
private JTextArea ta;
private JTextField tf;
private JButton b,b1,b2;
private JPanel p1,p2;
private Vector User; // 현재 사용하고 있는 채팅 멤버
private JFileChooser jfc = new JFileChooser("C://");
private JScrollPane jsp ;
private FileDialog fd;
//private FileListenThread flt;
private File file=null;
private String directory="";

public ChatClientForm(Socket s,Socket sf, String name)
{



this.s=s;
this.sf=sf;
this.name = name;
this.setTitle(name+"님의 채팅 클라이언트");

//////////////////////////////////////////


b1=new JButton("파일선택");
b1.addActionListener(this);
b2=new JButton("파일전송");
b2.addActionListener(this);
///////////////////////////////////
ta = new JTextArea();
jsp = new JScrollPane(ta);
ta.setEditable(false);
tf = new JTextField(25);
b = new JButton("전송");
b.addActionListener(this);
p1 = new JPanel();
p1.add(tf);
p1.add(b);
p1.add(b1);
p1.add(b2);


jsp.setWheelScrollingEnabled(true);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(p1,"South");
getContentPane().add(jsp,"Center");


setBounds(200,200,600,300);

try{
//서버로부터 문자열을 수신하기 위한 쓰레드를 생성한다.
ListenThread lt = new ListenThread(s,this);
Thread t = new Thread(lt);
t.start();
//FileListenThread flt = new FileListenThread(sf,this);
//Thread t1 = new Thread(flt);
//t1.start();


//서버에 문자열을 송신하기 위한 출력 스트림을 생성한다.
bw = new BufferedWriter(new OutputStreamWriter(s.getOutputStream()));

}catch(Exception e){

}

}
public void writerTextArea(String str){
ta.append(str +"\n");

}
public void actionPerformed(ActionEvent ae){
if(ae.getSource()==b)
try{
//버튼이 클릭되면 텍스트 필드의 내용을 서버에 송신한다.
bw.write(name+" : " +tf.getText() +"\n");
bw.flush();
tf.setText("");


}catch(Exception e){
//서버에 문자열을 송신할수 없으면 스트림과 소켓을 닫고
// 프로그램을 종료한다.
try{
bw.close();
s.close();

}catch(Exception e2){
System.exit(0);
}

}
finally{
System.out.println("채팅 소켓은 닫혔는가?"+s.isClosed());

}
if(ae.getSource()==b1){


try{

jfc.setDialogTitle("전송할파일");
//jfc.setMultiSelectionEnabled(true); ///다중선택 가능하게 만들기
jfc.showSaveDialog(this);
file= jfc.getSelectedFile();
tf.setText(file.getAbsolutePath());


}catch(Exception e){
try{
System.out.println("소켓이 닫혔습니다.");


}catch(Exception e2){

}
}


}






if(ae.getSource()==b2){
// 파일전송
try{
//버튼이 클릭되면 텍스트 필드의 내용을 서버에 송신한다.

osw = new OutputStreamWriter(sf.getOutputStream());
bw1 = new BufferedWriter(osw);
bw1.write(file.getName()+"\n");
bw1.flush();

byte[] buffer = new byte[1024];
System.out.println(file.length()+ "\n" + file.getTotalSpace());
int size = (int)(file.length()/buffer.length);

if(file.length()%buffer.length!=0){
size++;
}
System.out.println(size);
osw = new OutputStreamWriter(sf.getOutputStream());
bw1 = new BufferedWriter(osw);
bw1.write(size+"\n");
bw1.flush();


fis = new FileInputStream(file);
dis = new DataInputStream(fis);
dos = new DataOutputStream(sf.getOutputStream());
//1k씩 보냅니다.


System.out.println("에러1");
int len =0;

while((len = dis.read(buffer))!=-1){
//System.out.println(len);
System.out.println(buffer);
dos.write(buffer,0,len);
dos.flush();


}
file = null;


}catch(Exception e){

//서버에 문자열을 송신할수 없으면 스트림과 소켓을 닫고
// 프로그램을 종료한다.
try{
System.out.println("전송에 실패했습니다.");
if(osw!=null) osw.close();
if(bw1!=null) bw1.close();
if(fis!=null) fis.close();
if(dis!=null) dis.close();
if(dos!=null) dos.close();

//System.out.println("채팅 소켓은 닫혔는가?"+s.isClosed());
}catch(Exception e2){
System.exit(0);
}


}
finally{

System.out.println("채팅 소켓은 닫혔는가?"+sf.isClosed());

}
}
}
}





package Client;
import javax.swing.*;
import javax.swing.event.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;

public class InputForm extends JDialog implements ActionListener {

private JLabel ipl;
private JLabel port1;
private JTextField iptf;
private JTextField porttf;
private JButton b;
private JPanel ipjp;
private JPanel portjp;
private JPanel bjp;

private ChatClient c;


public InputForm(ChatClient c){
setTitle("서버 정보 입력 다이얼로그");
this.c =c;
ipl = new JLabel( "I P : ");
port1 = new JLabel("port : ");
iptf = new JTextField(15);
porttf = new JTextField(15);
b = new JButton ("입 력");
b.addActionListener(this);

ipjp = new JPanel();
portjp = new JPanel();
bjp = new JPanel();

ipjp.add(ipl);
ipjp.add(iptf);
portjp.add(port1);
portjp.add(porttf);
bjp.add(b);

setBounds(100,100,240,130);

getContentPane().setLayout(new GridLayout(3,1));
getContentPane().add(ipjp);
getContentPane().add(portjp);
getContentPane().add(bjp);
}

public void actionPerformed (ActionEvent ae){
//입력된 서버의 정보를 다이얼로그를 호출하는 클래스의 멤버변수에 저장한다.

c.setIp(iptf.getText());
c.setPort(Integer.parseInt(porttf.getText()));

c.setPortf(9401);
setVisible(false); // 실행이 끝난후에 지워준다.
//show(false);
}
}
package Client;

import java.io.*;
import java.net.*;

public class ListenThread implements Runnable {

private Socket s;
private ChatClientForm f;
private BufferedReader br;

public ListenThread (Socket s, ChatClientForm f){
this.s =s;
this.f =f;

try{
//인자로 받은 소켓에 대한 입력 스트림을 만든다.
br = new BufferedReader(new InputStreamReader(s.getInputStream()));

}catch(Exception e){

}
}
public void run(){

while(true){
//서버로부터 받은 내용을 읽어 클라이언트 텍스트 에어리어에 적는다.
try{
f.writerTextArea(br.readLine());

}catch(Exception e){

}
}
}

}



package Client;

import javax.swing.*;import javax.swing.event.*;
import javax.swing.border.*;
import java.awt.*;
import java.awt.event.*;

public class NameInputform extends JDialog implements ActionListener {

private ChatClient c;
private JTextField jf;
private JButton jb;
private JPanel jp1;
private JPanel jp2;

public NameInputform(ChatClient c){
this.c =c;
setTitle("대화명을 입력하세요");
setBounds( 100,100,250, 70);
jf = new JTextField(15);
jb = new JButton ("입 력");
jb.addActionListener(this);
jp1 = new JPanel();
jp2 = new JPanel();

jp1.add(jf);
jp2.add(jb);
getContentPane().setLayout(new BorderLayout());
getContentPane().add(jp1,"West");
getContentPane().add(jp2,"East");
}

public void actionPerformed ( ActionEvent ae){
//입력된 이름을 다이얼로그를 호출한 클래스의 멤버 변수에 저장한다.
c.setName(jf.getText());
setVisible(false);


}

}


댓글 달기

Filtered HTML

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

BBCode

  • 텍스트에 BBCode 태그를 사용할 수 있습니다. URL은 자동으로 링크 됩니다.
  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param>
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.

Textile

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • You can use Textile markup to format text.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Markdown

  • 다음 태그를 이용하여 소스 코드 구문 강조를 할 수 있습니다: <code>, <blockcode>, <apache>, <applescript>, <autoconf>, <awk>, <bash>, <c>, <cpp>, <css>, <diff>, <drupal5>, <drupal6>, <gdb>, <html>, <html5>, <java>, <javascript>, <ldif>, <lua>, <make>, <mysql>, <perl>, <perl6>, <php>, <pgsql>, <proftpd>, <python>, <reg>, <spec>, <ruby>. 지원하는 태그 형식: <foo>, [foo].
  • Quick Tips:
    • Two or more spaces at a line's end = Line break
    • Double returns = Paragraph
    • *Single asterisks* or _single underscores_ = Emphasis
    • **Double** or __double__ = Strong
    • This is [a link](http://the.link.example.com "The optional title text")
    For complete details on the Markdown syntax, see the Markdown documentation and Markdown Extra documentation for tables, footnotes, and more.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 사용할 수 있는 HTML 태그: <p><div><span><br><a><em><strong><del><ins><b><i><u><s><pre><code><cite><blockquote><ul><ol><li><dl><dt><dd><table><tr><td><th><thead><tbody><h1><h2><h3><h4><h5><h6><img><embed><object><param><hr>

Plain text

  • HTML 태그를 사용할 수 없습니다.
  • web 주소와/이메일 주소를 클릭할 수 있는 링크로 자동으로 바꿉니다.
  • 줄과 단락은 자동으로 분리됩니다.
댓글 첨부 파일
이 댓글에 이미지나 파일을 업로드 합니다.
파일 크기는 8 MB보다 작아야 합니다.
허용할 파일 형식: txt pdf doc xls gif jpg jpeg mp3 png rar zip.
CAPTCHA
이것은 자동으로 스팸을 올리는 것을 막기 위해서 제공됩니다.