자바로 C언어로 구현된 서버와 소켓 통신을 하려던 중 다음과 같은 예외가 발생하였다.

 

java.io.StreamCorruptedException: invalid stream header: 6572726F
   at java.io.ObjectInputStream.readStreamHeader(Unknown Source)
   at java.io.ObjectInputStream.<init>(Unknown Source)

 

 

원인은 예외메시지가 보여주는 것처럼 스트림헤더가 유효하지 않기 때문이었다.

 

C언어 기반의 서버와 통신하기 위해서는 ObjectStream이 아닌 DataStream을 사용해야 하는데

 

습관적으로 ObjectOutputStream과 ObjectInputStream를 사용해서 발생한 문제였다.

 

이것은 왜냐하면 JAVA 기반과 C언어 기반이 소켓통신을 하기 위해서는 read와 write를 할 때 byte 타입으로 해 주어야 하기 때문이다.

 

다음은 C언어 기반의 서버에 소켓을 연결해서 한 번 메시지를 주고받는 JAVA 클라이언트의 예제 소스이다. 서버의 소스는 포함하지 않는다.

 

Example.java

import java.io.DataInputStream;
import java.io.DataOutputStream;
import java.net.InetSocketAddress;
import java.net.Socket;

public class Example {

	private static final String serverIP = "1.234.56.78";	// your serverIP
	private static final int portNum = 1234;		// your port number
	private static final int buffersize = 100;

	private Socket mSocket = null;
	private DataOutputStream mObjOStream = null;
	private DataInputStream mObjIStream = null;

	public Example()
	{	
	}
	
	public static void main(String args[])
	{
		Example example = new Example();
		example.connect();
	}

	public void connect()
	{
		try
		{
			mSocket = new Socket();
			mSocket.connect(new InetSocketAddress(serverIP, portNum));
			mObjOStream = new DataOutputStream(mSocket.getOutputStream());
			mObjIStream = new DataInputStream(mSocket.getInputStream());
			System.out.println("connection successed");
			
			byte[] out = new byte[buffersize];
			String sendmgs = "kugistory.net";	// your sending message
			out = sendmgs.getBytes();
			mObjOStream.write(out);
			mObjOStream.flush();
			System.out.println("message sended: " + sendmgs);
			
			byte[] in = new byte[buffersize];
			mObjIStream.read(in,0,in.length);
			String response = new String(in,0,in.length);	// your receiving message
			response.trim();
			
			System.out.println("response=" + response + "@end");
			mSocket.close();
		}
		catch ( Exception e )
		{
			e.printStackTrace();
		}
	}
}

Posted by Kugi
,



다음은 안드로이드에서 MediaRecorder와 MediaPlayer를 이용하여 소리를 녹음하고  재생하는 예시이다.

 

 

 


 

 

setAudioSource() : 소리를 어디서부터 받아올지 설정한다.

  마이크를 녹음하거나 통화 중 목소리 녹음, 통화 중 발신자 목소리만 녹음, 통화 중 수신자 목소리만 녹음 등을 결정한다.

 

setOutputFormat() : 녹음 파일의 데이터 형식(format)을 설정한다.

 

setAudioEncoder() : 인코더(코덱)을 설정한다.

 

setOutputFile() : 녹음 파일의 경로 및 이름을 설정한다.

Posted by Kugi
,



어플리케이션을 개발하다 보면 파일을 외장메모리 등에 저장해야 할 필요가 있다.

 

특정 경로를 지정해줬는데, 만약 해당 경로가 존재하지 않으면

 

error: No such file or directory

와 같은 에러를 뱉어내곤 한다.

 

해결하기 위해서는 다음과 같은 방법을 사용한다.

 

 

파일을 생성하기 전에 원하는 경로가 존재하는지 확인하고 만약 경로가 존재하지 않으면 생성한 후

 

파일을 생성할 경로를 반환해주는 메소드이다. 외장메모리의 유무도 확인한다.

 

	// Example
	public static synchronized String GetFilePath(int fileType, int fileId)
	{
		String sdcard = Environment.getExternalStorageState();
		File file = null;
		
		if ( !sdcard.equals(Environment.MEDIA_MOUNTED)) 
		{ 
			// SD카드가 마운트되어있지 않음
			file = Environment.getRootDirectory();
		}
		else
		{
			// SD카드가 마운트되어있음
			file = Environment.getExternalStorageDirectory();
		}

		
		String dir = file.getAbsolutePath() + String.format("/mytestdata/file_%02d", fileType);
		String path = file.getAbsolutePath() + String.format("/mytestdata/file_%02d/myfile%04d.mp4", fileType, fileId);

		file = new File(dir);
		if ( !file.exists() )
		{
			// 디렉토리가 존재하지 않으면 디렉토리 생성
			file.mkdirs();
		}
		
		// 파일 경로 반환
		return path;
	}

 

* 참고로 File 클래스의 멤버메소드에는 mkdirs()와 mkdir()이 있는데

 

 이름 그대로 mkdirs()는 목적지 경로까지 상위폴더를 포함하여 전체 경로를 생성하고, mkdir()은 지정한 폴더 하나만을 생성한다.

 

 둘 다 반환타입은 boolean으로, 경로 생성에 성공하면 true, 이미 존재하는 경로이거나 실패하면 false를 반환한다.

Posted by Kugi
,



윈도우즈 콘솔 창의 크기를 변경하고 싶다면 다음의 커맨드를 입력하면 된다.

 

mode con: lines=n cols=n

 

변수를 입력하지 않으면 현재 상태를 출력해준다.

 

콘솔 창의 크기가 변경 된 모습

 

cmd 창을 새로 열면 원래 사이즈로 열린다.

Posted by Kugi
,



3차원 좌표계를 표현할 땐 보통 아래의 그림과 같은

 

왼손 좌표계(left-handed coordinate system)와 오른손 좌표계(right-handed coordinate system) 두 가지 방법을 이용한다.

 

 

 

오른손 좌표계는 근 100여년 동안 표준적으로 사용되어온 방법이다. 물리학계를 비롯해 OpenGL 등 대부분은 이 좌표계를 사용한다.

 

왼손 좌표계를 사용하는 대표적인 사례로는 Direct3D가 있다.

 

이 두 좌표계를 외우는 방법은 다양하겠지만 필자의 경우 다음과 같은 방법으로 숙지했다.

 

  1. 박수 칠 때 처럼 양 손을 마주 보도록 펼친다. 이 때 엄지손가락은 나머지 손가락과 직각이 되도록 한다.

 

  2. 가운뎃손가락을 손바닥에 수직이 되도록 반 쯤 접고, 약손가락과 새끼손가락은 완전히 접는다.

 

  3. 마치 '쌍권총 자세'를 연상케하는 모양이 되었을 것이다.

 

     왼손은 엄지손가락부터 순서대로

 

     [엄지손가락-x, 집게손가락-y, 가운뎃손가락-z]

 

     오른손은 반대 순서로

 

     [엄지손가락-z, 집게손가락-y, 가운뎃손가락-x]

 

     이런 식으로 대응시킬 수 있다.

 

이 상태로 양 손의 집게손가락을 하늘을 향하게 해서 위의 그림에 나온 좌표계와 비교해보자.

 

똑같은 배치가 되어있음을 알 수 있을 것이다.

Posted by Kugi
,