안녕하세요, 날씨는 추우신데 감기는 안걸리셨나요..?
저는 몸살감기 걸려서 어제 궁디에 주사 놓고 왔습니다..ㅠ.ㅠ
여러분 모두 감기 조심하세요 흑흑....
다름이아니라, 안드로이드에서 컴퓨터로 파일을 전송하는 어플을 만들어보고 있는데요~
방식은 TCP/IP 소켓통신이머 Wifi 내부망에서 작동해보았습니다.
1보낸 이미지 크기는 10.8KB 입니다. 기존에 100KB정도 되는파일 해보다가 바꿔보았습니다.
전송은 아주 잘 됩니다... 그런데!!
몇가지 증상이 있습니다....!
1. 이미지 짤림은 다음과 같이 나옵니다...
2. null이라는 확장자도 없는 파일이 함께 1 + 1 행사하듯이 보내집니다...(뜨헉..)
파일관련된 부분은 처음이라 이정도까지밖에 설명을 못드리네요 ㅠㅠ
대신 각 소스코드 올려바치겠나이다 ( _ _ )
Android Activity 파일전송 부분
try { Log.i("로그","두번째이상 클릭"); //★★★★★★★로그켓 str = edit.getText().toString(); //str변수에 에디트텍스트값 넣음 PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(socket.getOutputStream(),"MS949")),true); out.println(str); Log.i("로그","보냄"); //★★★★★★★로그켓 out.flush(); DataInputStream dis = new DataInputStream(new FileInputStream(new File("/mnt/sdcard/1.jpg")));
DataOutputStream dos = new DataOutputStream(socket.getOutputStream()); byte[] buf = new byte[10800]; while(dis.read(buf)>0) { dos.write(buf); dos.flush(); } dos.close(); } catch (IOException e) { // TODO Auto-generated catch block Log.i("로그","두번째이상 클릭에서 오류"); //★★★★★★★로그켓 }
Java 파일 수신 서버 전체코드
import java.io.BufferedReader;
import java.io.File;
import java.io.FileOutputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
public class TCPServer implements Runnable{
public static final int serverPort = 30001;
@Override
public void run(){
try{
System.out.println("대기중..");
ServerSocket serverSocket = new ServerSocket(serverPort);
while(true)
{
Socket sock = serverSocket.accept();
System.out.println("수신중....");
try{
BufferedReader in = new BufferedReader(new InputStreamReader(sock.getInputStream()));
String str = in.readLine();
System.out.println("수신중인 파일 이름 : " + str);
File f = new File("c:\\down\\", str+".jpg");
FileOutputStream output = new FileOutputStream(f);
byte[] buf = new byte[10800]; while(sock.getInputStream().read(buf)>0)
{
output.write(buf);
output.flush();
}
in.close();
output.close();
System.out.println(str+".jpg 수신완료");
}
catch(Exception e){
System.out.println("서버 에러!!");
e.printStackTrace();
}
finally{
sock.close();
}
}
}
catch(Exception e){
e.printStackTrace();
}
}
public static void main(String[] argv){
Thread doit = new Thread(new TCPServer());
doit.start();
}
}
실력없는 초보놈이 여러분들께 자문을 구하오니, 부디 뿌리치지 마시옵고
넓은 아량으로 살펴주시옵소서 ㅠ.ㅠ
──────────────────────
inputStream 계열의 메서드인 read 가 데이터를 읽은 수를 리턴해줍니다. 따라서 위 로직상에는 파일 사이즈를 따로 보낼필요는 없고
read 의 리턴 값을 통해 얼만큼 받아왔는지 또는 읽었는지 확인하시면 됩니다.
따라서 buffer 의 크기는 고정으로 하시고 read 해서 읽은 만큼만 write 하실때 매개변수로 넣어주시면 됩니다.
void wrtie(byte[] buffer, int offset, int length)
위는 write 메서드의 원형이고요, offset 은 바이트 배열인 buffer 에서 write 할 시작 위치를 의미하고,
length 는 offset 위치로 부터 몇개의 데이터를 보낼지 지정하는 인자 입니다.
추가적으로 클라이언트에서 소켓의 outputstream을 DataOutputStream 으로 변환하실 필요가 없습니다. DataOutputStream 은 int double, char 처럼 기본 데이터타입(primitive type) 을 전송할때 읽고 쓰기의 편의성을 위해서 사용하는 것이고요. 지금 처럼 그냥 byte 형태의 데이터는 그냥 Outputstream 사용하셔도 무방합니다.
마지막으로 null 이 생성되는 부분은 서버쪽에서 혹시 exception 발생되는 부분 없나요? 아마 그거 관련되서 오류가 나는것 같은데요.
재질문이 조금 늦었는데 보실지 모르겠습니다만..ㅠ.ㅠ
write할때 매개변수로 넣으면 된다고 하셨는데요~
dos.write(buf, 0 , read_length);
이렇게 수정을 하였습니다.
사실 제가 잘 이해가 안가는 부분이 buf ,0 ,read_lenth가 순서대로 열거하자면
바이트배열 , 시작위치 , 몇개를 보낼지.. 이렇게라는 이야기인데..
앞서 말씀하신걸 보면 '파일사이즈를 보낼 필요는 없고.."라고 한다면
이건 서버에서 해야한다는 말씀이신가요?
지식수준이 낮아서 이해가 어렵습니다... 추가설명을 부탁드려도 될지..ㅠ.ㅠ
뒷부분 이미지가 이상하게 나오는건..
read 해서 읽은 데이터의 수 만큼만 소켓에 write 하셔야하는데..
갯수 체크 따로 하시지 않고 buf 데이터를 그대로 보내셔서 문제가 되는것 같습니다.
파일을 읽을때 버퍼 사이즈인 10800 만큼 읽어 들이시는데, 파일의 총 사이즈가 10800 에 나누어 떨어지는 확률이 거의 희박하기에..
파일 데이터의 끝자락에서는 10800 보다 적은 양의 데이터만 읽게 될것 입니다.
하지만 10800 보다 적게 읽어들였는데, write 에서 별도의 사이즈를 지정하지 않으셨기 때문에 write는 10800 만큼 데이터를 보내게 됩니다. 10800 보다 작은 원데이터에 불필요한 데이터들이 함께 보내지기 때문에 이미지의 마지막 부분이 그렇게 깨지는것입니다.
아래와 같이 수정하셔야 하며, 읽은 데이터의 양을 체크하는게 반드시 필요합니다.
byte[] buf = new byte[10800];
int read_length = 0;
while((read_length = dis.read(buf)) > 0 )
{
dos.write(buf, 0 , read_length);
dos.flush();
}
dos.close();
널 파일이 생기는 이유는 잘 모르겠네요 ~_~;