안녕하세요~도무지 해보다가 해결이 안되는 질문이 있어서 이렇게 올리게 되었습니다ㅠ
자바로 클라이언트-서버 통신을 시도하는데 socket갯수에 대해 이해가 안되는 부분이 있어서요~!ㅠ
1.
먼저 java socket에관련된 질문이 있는데요,
제가 안드로이드 프로그래밍을 진행하며 현재 소켓통신을 시도하여 서버(개인 pc)와 통신을 시도합니다.
소켓을 통해서 이미지와 텍스트파일들이 오가는데요,
처음에 소켓을 왔다리 갔다리 1개를 만들어 진행했는데
전송도중 멈추는 현상이 발견되었습니다.
Socket socket1 = new Socket(serverAddr, serverPort);//Image send Socket
다음과 같이 열어주었었고 DataInput, DataOutput stream을 열어주어서 서로 이미지가 송,수신되던도중
멈추더군요..
OutputStream output = socket1.getOutputStream();
FileInputStream C_image =
new FileInputStream(new File("/mnt/sdcard/folder","image"+ ".jpg"));
DataOutputStream dos = new DataOutputStream(output);
byte[] buf = new byte[4096];
while(C_image.read(buf) != -1){
dos.write(buf);
dos.flush();
}
마찬가지로 receive부분도 이런식으로 해줬습니다.
1개의 이미지와 1개의 텍스트가 서버로전송되고 클라이언트는 1개의 이미지와 1개의 택스트를받는
총 4개의 파일이 송수신되는 형태였습니다.
저는 이것을 한 소켓에서 해줬습니다.
그래서 해결책으로 소켓을 4개로 나누어서 진행했더니 그런 오류가 말끔히 사라졌습니다.
도중에 멈추지 않고 제대로 진행되더군요..
순서상 각각의 파일들이 동시에 전송되는바람에 한 소캣에서 멈추는것도 아니었고
순차적으로 파일이 왔다리 갔다리 하는데 왜 소켓이 송수신 갯수만큼 생기면 이상이 없는것인지 궁금합니다.
찾아보다가도 명확한 이유를 설명해놓은것을 못봐서 이렇게 질문을 드려봅니다^^;
2.두번째는 긴 질문은 아니고 책추천부탁드리는 질문입니다^^ㅎㅎ
현재 "안드로이드정복"이라는 책을 보고 있는데 전반적인 설명이 코딩기술을 설명하고있었습니다.
그러나 체계적으로 안드로이드의 동작원리를 공부해보고 싶은데
책 추천이나 참고사이트부탁드립니다^^;
3.
더불어 영상처리관련 책도 곤잘레스책의 경우 압축기술 위주로 나와있는데
수학적개념 위주보다 초보자이다보니 쉽게 접근할수있을만한 영상처리관련 책은 없는지요?^^;
학생인지라 질문이 횡설수설 너무 많은것을 질문한것같습니다 ㅎㅎ
긴글 읽어주셔서 감사드립니다.
고수님들의 가르침 부탁드립니다^^
소켓 하나를 생성하고 그 소켓으로 순차적으로 파일을 보내셨는데 전송이 중단되었단 말씀이신가요?
파일의 갯수만큼 소켓을 생성하고 각각의 소켓으로 전송하니까 데이터가 모두 잘 전송이 되었구요...?
저도 잘은 모르지만 제가 이해하고 생각하기론...
버퍼 크기 떄문이라고 생각되네요.
각각의 소켓이라면 버퍼의 크기가 제한적이더라도 데이터의 끝이 전송될때까지 즉, 모든 데이터의 전송이 끝날때까지 연이어 보낼것이므로 전송이 성공할 것같구요.
하나의 소켓으로 각각의 데이터 전송이 끝난뒤 다음 데이터를 전송하도록 코딩을 하셨다면
버퍼의 크기만큼만 전송을 하고 다음 데이터 전송으로 넘어간것이 아닐까 생각이 드네요...
클라이언트에서 이미지 소스에 대한 bytearray와 소켓내의 buf[] 데이터를 같이 확인해보세요.
좋은의견감사합니다^^
사실 이 문제로 하루종일 고민했었는데요..전송이 아예안되는것도 아니었고 일정부분 되다가 멈추더군요.
저도 리눅스에서 서버-클라이언트로 FTP만드는 프로젝트해봤을때도 그렇게 배웠었거든요.
또한 채팅프로그램 예제에서도 소켓하나로 주고받구요. 분명 다 전송할때까지 while문을 돌렸는데 전송이 되다가 멈추더라구요 ㅠ;;;
멈추는게 마치 서로 send, receive 부분이 짝이 안맞는것과같더군요 ㅠ;
도무지 이해가 되지않아서 이렇게 올려봤네요 ㅠㅎㅎ 의견 감사합니다!
말씀하신 버퍼크기부분을 크게 잡아봐야겠습니다ㅎ
버퍼에서 읽어들인 사이즈만 전송을 하셔야 하는데 무조건 버퍼에 사이즈 만큼 무조건 전송하시도록 되어있네요.
저렇게 되면 전송시에 쓰레기 데이타도 전송이 되거나 에러가 떨어질듯 합니다. 문자열에 마지막 바이트가 null이듯이 파일도 비슷하게 구현되어 있을듯 한데, 혹시 원본 데이타로 전송시에는 정상 전송되나, 저장된 파일로 다시 전송시 멈추는건 아니신지요??
옙..저도 파일의 끝을 몰라서 멈춘다고 생각해서 파일의 맨끝에 null값을 넣어주거나 했는데 멈추는건 같았습니다 ㅠ
그리고 소켓을 여러개 나누어서 송,수신시에는 파일이 서로 정상적으로 통신되었구요..음..
제가 가장 궁금한점은 왜 소켓을 여러개 나눴을때 전송도중 멈추는 현상이 사라진건지 궁금합니다 ㅠ;
이 얘기는 대용량(일반 스트링보다 크기가큰)의 정보가 전달되어질때 한정된 소켓으로 통신할때 어떠한 충돌이 일어나는게 아닌가싶은데
이부분이 추측에 불과해서요 ㅠ 보통 이렇게 전송도중 멈추는경우가 있을땐 리눅스에서 FTP만들때 배웠기로는 read, write함수의 짝맞춤이 안됐을 경우였던것 같은데 이때는 그것도 아니었거든요ㅠ 왜이럴까요?ㅠㅠ;;
근데 소스 내용으로는 파일 1개만 전송하는 걸로 돼 있는데, 스레드를 쓰시나요? 혹시 파일별로 스레드를 따로 해주신건 아닌지....그러면 스레드 충돌로 당연히 멈출거 같아서요.....
위 소스에서는 close가 없네요(아마 설명을 위해 생략하신거라 생각됩니다)
소켓 하나만 이용 하나씩 전송후 close(finally 구문 안에 위치) <-- 소스에 안보여서 적어 봤습니다.
소켓프로그램에 대해 좀더 알고 싶으시면, 오렐리에서 나온 Java Network Programming
번역된것이 있는지 모르겠는데 아마 도움이 될겁니다.
저도 네트워크 프로그래밍을 잘하는 것은 아니지만..일단 클라이언트에서 이미지 먼저 보내고 다시 텍스트를 보내는 식으로의 순차적인 프로그래밍이 되는지가 궁금하네요..
물론 보내는 쪽에서 send 메소드에 보내는 것을 두번으로 해서 보내고 받는 쪽에서 두번으로 받는다고 해도..그것에 대한 동작 보장을 할 수 있을지가 의문이네요..
만약 저라면..걍 한번에 보내겠습니다..
무슨 의미냐면..
이미지 파일이든 텍스트 파일이든 byte 배열로의 변환이 가능합니다..그러면 자체 메시지 규격을 만들어서 보내는 것이지요..
규격을 대강 예를 드리자면..
하나의 byte 배열로 보내는데..
전체길이-이미지 파일명 길이-이미지 파일명-이미지 데이터 길이-이미지 데이터 byte 배열-텍스트 파일명 길이-텍스트 파일명-텍스트 데이터 길이-텍스트 데이터 byte 배열
요런식으로 메시지 규격을 잡고 이것들을 하나의 byte 배열에 넣은뒤에 보내는 겁니다..여기서 길이 라는 것은 파일명이든 파일 데이터든 byte 배열로 변환했을때의 그 길이가 됩니다. 그래야 나중에 그 길이만큼 해당 파트를 읽어서 복원시키는거죠..
그러면 받는 쪽에서는 이 byte 배열을 받아다가 각 파트별에 저장된 길이 데이터를 읽어서 각 파트별로 복원을 시키는거죠..
그러면 1개의 소켓이라 해도 한번 전송으로 끝납니다..
자바에서 자체적으로 제공하는 FileInputStream 같은 걸로 보내는 방법은 편리는 하지만..응용하는 부분에 있어서는 제약이 따르는 부분이 있습니다. 제가 알기로는 그렇게 할려면 서버와 클라이언트 모두 자바로 구현해야 하는 걸로 알고 있습니다.그래서 호환에서 문제의 소지가 있구요(예를 들어 서버나 클라이언트가 자바가 아닌 C나 C++로 구현 할 경우 호환이 안됩니다..)
때문에 조금 복잡할수는 있어도 모든 언어에서 호환되는 구조인 byte 데이터 구조를 이용하여 이것을 배열로 해서 보내는거죠..이렇게 하면 여러개의 데이터가 존재한다 해도 메시지 구조 정의를 잡은뒤 모든 데이터를 byte 배열로 변환해서 넣으면 여러개의 데이터라 해도 한번에 전송이 가능합니다..
긴답글 감사합니다 ^^
저도 예전에 어디서 봤는데 자바<->C,C++의 소켓통신시에 우려할부분은 빅엔디안방식과 리틀엔디안방식의 차이 이외엔
조심할것이 없다고 어디서 본것같아요 ㅎㅎ 일단 이러한 귀찮은점을 고려하기 싫어서 전 자바<->안드로이드 통신을 했지만요 ㅎㅎ
먼저 "클라이언트에서 이미지 먼저 보내고 다시 텍스트를 보내는 식으로의 순차적인 프로그래밍이 되는지가 궁금하네요.."
이부분에 대한 답변을 드리자면 소켓을 각각나눠줬을때는 순차적으로 가능했습니다ㅎ
이미지 보내고 다 끝나면 텍스트 보내고 이런식이요 ㅎㅎ
말씀하신 한번에 보내는방법도 괜찮은것 같군요..흠..그렇다면 소켓을 여러개로 나누어서 전송했을때의 단점은 없을까요?
사실 "동작은 되니깐 바꿔주기 귀찮다(?)" 이게 제 무의식속의 외침이군요 ㅠ 소켓을 여러개 뒀을때의 단점이나 장점,문제점
하나의 소켓으로만 보냈을때의 단점이나 장점,문제점 등을 알고있었으면 해서요 ㅠ
통신시에 소켓을 여러개로 나눴다는 부분을 발표할때 얘기해야하거든요 ㅎ
"오류가났는데 소켓을 늘려줬다. 그랬더니 해결됐다" 이렇게 말할수가 없기에 이렇게 이유를 알고싶습니다 흑..ㅠㅠ
댓글 달으신것을 이제 보았네요..
저도 정확하게 말씀 드릴수 있을 만큼의 지식이 있는 것은 아니지만..
2가지 측면에서 장단이 나올수가 있을듯 합니다..전체적인 작업속도와 리소스 관리이죠..
클라이언트에서 소켓을 2개 이상 한다는 것은 서버도 결국 한 사용자의 작업에 대한 처리를 할때 클라이언트의 소켓 갯수만큼 동시에 받는 거겠죠..이렇게 하면 전체적인 작업 처리 속도는 빠르게 될수 있겠지만..객체를 그만큼 더 사용하기 땜에 리소스 관리차원을 생각해봐야 할 부분이 있습니다..물론 클라이언트에서는 소켓 갯수가 많아진다고 리소스 관리에서 무슨 큰 문제가 발생하는 그런 문제는 없습니다만..동시에 여러 사용자를 받아야 하는 서버 입장에서는 이 부분은 중요하게 될 수 있구요..
그래서 만약 통신을 하기 위한 동접자수가 작거나 또는 접속 빈도가 낮다면 여러개의 소켓을 써도 무리는 없을것 같지만..만약 동접자수가 크거나 접속빈도가 자주 발생한다면 처리 속도를 희생하더라도 안정적으로 전송되게끔 보장해야 할 필요는 있다고 봅니다..




버퍼의 크기를 늘려보세요