Hiredis SMEMBERS 활용

Programming/Redis 2017. 1. 24. 13:34 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

Hiredis SMEMBERS 활용








	redisReply *reply;
	redisAppendCommand(context, "SMEMBERS myset");
	redisGetReply(context, (void**)&reply);
	for (int i = 0; i < reply->elements; i++)
	{
		// reply->element[i]->str; // myset
	}

	freeReplyObject(reply);












참고 : https://redis.io/commands/smembers

참고 : https://github.com/redis/hiredis/blob/master/examples/example.c



'Programming > Redis' 카테고리의 다른 글

Redis Client Connect Test  (0) 2016.10.26
Hiredis Subscribe/Publish with CWinThread  (0) 2016.10.05
How to use Pub/sub with hiredis in C++?  (0) 2016.09.29
hiredis fatal error C1853:  (0) 2016.09.29
hiredis MFC import Visual Studio 2013  (0) 2016.09.28

CWnd::Invalidate

Programming/MFC 2016. 11. 15. 09:34 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

CWnd::Invalidate

void Invalidate(
   BOOL bErase = TRUE 
);
bErase

Specifies whether the background within the update region is to be erased.

The client area is marked for painting when the next WM_PAINT message occurs. The region can also be validated before a WM_PAINTmessage occurs by the ValidateRect or ValidateRgn member function.

The bErase parameter specifies whether the background within the update area is to be erased when the update region is processed. If bEraseis TRUE, the background is erased when the BeginPaint member function is called; if bErase is FALSE, the background remains unchanged. If bErase is TRUE for any part of the update region, the background in the entire region, not just in the given part, is erased.

Windows sends a WM_PAINT message whenever the CWnd update region is not empty and there are no other messages in the application queue for that window.




Invalidate(FALSE)  ->  WM_PAINT

Invalidate(TRUE)   ->  WM_ERASEBKGND   -> WM_PAINT




MFC Dialog Position Save & Load

Programming/MFC 2016. 11. 10. 11:45 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

MFC Dialog Position Save & Load


참조 : http://www.codeproject.com/Articles/1154/Saving-a-windows-size-position-and-state-in-MFC


Saving the window placement








BOOL CMainFrame::DestroyWindow() 
{
    WINDOWPLACEMENT wp;
    GetWindowPlacement(&wp);
    AfxGetApp()->WriteProfileBinary("MainFrame", "WP", (LPBYTE)&wp, sizeof(wp));

    return CMDIFrameWnd::DestroyWindow();
}






Restoring the window placement









void CMainFrame::OnShowWindow(BOOL bShow, UINT nStatus) 
{
    CMDIFrameWnd::OnShowWindow(bShow, nStatus);

    static bool bOnce = true;

    if(bShow && !IsWindowVisible()
        && bOnce)
    {
        bOnce = false;

        WINDOWPLACEMENT *lwp;
        UINT nl;

        if(AfxGetApp()->GetProfileBinary("MainFrame", "WP", (LPBYTE*)&lwp, &nl))
        {
            SetWindowPlacement(lwp);
            delete [] lwp;
        }
    }
}







'Programming > MFC' 카테고리의 다른 글

[MFC] Dialog 닫기 (OnOK/EndDialog)  (0) 2017.02.08
CWnd::Invalidate  (0) 2016.11.15
MFC - 다이얼로그 생성시 발생되는 메세지들...  (0) 2016.11.07
MFC x64 ADO msado15.dll  (0) 2016.10.28
x64 ADO import  (0) 2016.10.28
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

출처 : http://namacin.egloos.com/1368314



MFC - 다이얼로그 생성시 발생되는 메세지들...

다이얼로그가 생성될 때 발생되는 메세지의 순서로는

DoModal()
PreSubclassWindow()
OnNcCreate()
OnNcCalcSize()
OnCreate()
OnSize()
OnMove()
OnSetFont()
OnInitDialog()
OnWindowPosChanging()
OnMove()
OnWindowPosChanged()
OnWindowPosChanging()
OnNcActivate()
OnActivate()
OnShowWindow()
OnWindowPosChanging()
OnNcPaint()
OnEraseBkgnd()
OnChildNotify()
OnCtlColor()
OnWindowPosChanged()
OnPaint()
OnCtlColor()
OnCtlColor()
OnNcHitTest()
OnSetCursor()
PreTranslateMessage()
OnMouseMove()
OnNcHitTest()
OnSetCursor()
PreTranslateMessage()


클래스 위자드에서 메세지 필터를 Window로 주고 발생하는 모든 메세지에 대해서
간단한 문자 출력용 핸들러를 주었다.

이 상황에서 아무것도 없는 기본 다이얼로그 화면을 DoModal() 함수로 띄웠을 때 
발생하는 메세지들을 캡쳐한것이다.

어떠한 핸들러들은 afx_msg 함수로 메세지 맵에 등록되고 어떠한 함수들은
vitual로 선언되며 메세지 맵에 등록되지 않았다. 이렇게 구분되는 기준은 무얼까?


%%
메세지 맵에 등록되는 함수(핸들러) 들은 정말 윈도가 뿌려대는 메세지에 대한
핸들러이고 virtual로 선언되는 함수들은 메세지에 대한 핸들러가 아니라
프로세스가 진행되면서 당연히 호출되는 함수들이 아닐까 생각된다.

 

어떠한 핸들러들은 publc으로, 어떠한 핸들러들은 protected로 선언된다.
(메세지 맵에 등록된 핸들러들은 모두 protected이다.)

중요한지 아닌지는 모르겠지만 차근차근 알아봐야할 내용들..

 


[메세지에 대한 설명은 www.winapi.co.kr 에서 발췌]

DoModal - 
PreSubclassWindow -

WM_NCCREATE - 
WM_NCCALCSIZE - 
WM_CREATE - 
WM_SIZE - 
WM_MOVE - 
WM_SETFONT - 
WM_ONINITDIALOG - 
 다이얼로그가 메모리에 만들어지고 화면에 보이기 적전에 보내진다고 한다.
 오버랩드 윈도우의 WM_CREATE에 해당한다는데...
 
WM_WINDOWPOSCHANGING - 
WM_MOVE - 
WM_WINDOWPOSCHANGED - 
WM_WINDOWPOSCHANGING - 
WM_NCACTIVATE - 
 비 작업영역(client영역을 제외한 영역을 말하는것이 아닐까..)에 대한 활성 
 또는 비 활성화시 변경되는 내용이 있을 때 보내진다고 한다.
 
WM_ACTIVATE - 
 WM_NCACTIVATE가 비 작업 영역에 대한 메세지라면 이 메세지는 작업영역에 대한
 처리를 위한 메세지..

WM_SHOWWINDOW - 
 윈도우의 보임 상태가 변경되기 직전에 보내진다고 한다. WS_VISIBLE 스타일을 가진 윈도우가
 생성될 때도 보내진다고 한다.
 
WM_WINDOWPOSCHANGING - 
WM_NCPAINT - 
 비 작업 영역을 그려야 할 때 발생한다고 한다
 
WM_ERASEBKGND - 
 윈도우 크기가 변경 되었거나 다른 윈도우에 가려진 부분이 드러났다거나 할 때 배경을 지우기 위해
 이 메셎가 보내진다고 함. WM_PAINT에서 출력하기 전에 먼저 그려진 내용을 지워야 하는데 이 메세지에
 대해 처리를 하지 않으면 "윈도 클래스에 등록된!!" 디폴트 배경 브러시로 지운다고함.
  
 %% 윈도 클래스 배경 브러시가 NULL 일경우 아무것도 하지 않음.
 
WM_CHILDNOTIFY - 
WM_WINDOWPOSCHANGING - 
WM_PAINT - 
 1. 윈도우가 처음 생성되었을 때
 2. 윈도우의 위치가 이동되었을 때
 3. 윈도우의 크기가 변경, 최소, 최대화 되었을 때
 4. 다른 윈도우에 가려져 있다가 드러날 때
 5. 스크롤 될 때
 발생한다고 한다.
 
WM_CTLCOLOR - 
 윈도우가 그려질 필요가 있을 때 발생되어 브러시의 색상을 지정하게 된다.
 
WM_CTLCOLOR - 
WM_NCHITTEST - 
 마우스를 이동하거나 버튼을 누르거나 놓을 때마다 발생. 커서가 있는 위치가 윈도우의 어디쯤인지를
 윈도우에게 질문을 하며 운영체제닌 이 메세지의 리턴값에 따라 마우스를 처리한다고 한다
 
WM_SETCURSOR -

PreTranslateMessage -

뒤로

WM_MOUSEMOVE
WM_NCHITTEST
WM_SETCURSOR

의 메세지가 연속적으로 나오는데 이 메세지는 다이얼로그 생성과는 관계가 없는듯..
또, 각 메세지들의 중간중간에 WindowProc, DefWindowProc, WM_CTLCOLOR, PreTranslateMessage
메세지가 매우 자주 섞여 나왔다.


'Programming > MFC' 카테고리의 다른 글

CWnd::Invalidate  (0) 2016.11.15
MFC Dialog Position Save & Load  (0) 2016.11.10
MFC x64 ADO msado15.dll  (0) 2016.10.28
x64 ADO import  (0) 2016.10.28
MSSQL 테이블명, 컬럼명 검색  (0) 2016.10.27

임계영역 설정 Ctirical Section

Programming/C,CPP,CS 2016. 11. 7. 11:07 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

임계영역 설정 Ctirical Section








CreateMutex
Critical Section Objects
DeleteCriticalSection
EnterCriticalSection
InitializeCriticalSectionAndSpinCount
LeaveCriticalSection
Synchronization Functions
TryEnterCriticalSection






void WINAPI InitializeCriticalSection( LPCRITICAL_SECTION lpCriticalSection );

void WINAPI DeleteCriticalSection( LPCRITICAL_SECTION lpCriticalSection );

void WINAPI EnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection );

void WINAPI LeaveCriticalSection( LPCRITICAL_SECTION lpCriticalSection );

BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection );








1. 임계영역 변수선언

CRITICAL_SECTION cs;


2. 초기화

InitializeCriticalSection( &cs );


3. 사용


임계영역 진입

EnterCriticalSection( &cs );


임계영역 탈출

LeaveCriticalSection( &cs );


4. 삭제

DeleteCriticalSection( &cs );






Jsoncpp 주의 사항

Programming/C,CPP,CS 2016. 11. 1. 12:05 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.





Json::Value  retrieve_list= NULL;



둘은 다르다.


Json::Value  retrieve_list;

'Programming > C,CPP,CS' 카테고리의 다른 글

[jsoncpp] getList Names  (0) 2017.02.06
임계영역 설정 Ctirical Section  (0) 2016.11.07
OpenSSL x86 Build  (0) 2016.10.28
pjproject-2.5.5  (0) 2016.10.14
pjsip Building for Microsoft Windows  (1) 2016.10.12

MFC x64 ADO msado15.dll

Programming/MFC 2016. 10. 28. 18:05 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

MFC 에서


x64 환경에서


ADO msado15.dll 를 사용하고 싶었다.







#import "c:\Program Files\Common Files\System\ADO\msado15.dll" rename("EOF", "EndOfFile")




1. tlh 파일 추출하기

#import "C:\Program Files\Common Files\System\ado\msado15.dll" no_namespace rename("EOF", "adoEOF") rename("BOF", "adoBOF")

 

구문을 그대로 두고 컴파일을 진행 한다.

 

컴파일이 성공하면 Object 파일들이 생성 되는 Debug 폴더 또는 Release 폴더로 가보자.

 

#import 처리기가 하는 역할이 dll 에서 tlh 를 추출하여 헤더 파일에 그대로 붙여 넣는 작업을 해주는 역할이기 때문에 Debug 폴더나 Release 폴더에 가보면 다음과 같은 파일이 보일것이다.

 

msado15.tlh

msado15.tli

 

각각 용량은 167KB, 146KB 정도로 꽤 큰편이다.

 

위 두파일을 복사해서 #import 구문을 사용했던 소스와 동일한 경로에 붙여넣기 한다.

 

#import ".........

코드를 다음과 같이 변경한다.

#include "msado15.tlh"

 

이렇게 하면 #import 로 추출된 tlh 파일을 include 하는 구조이기 때문에 동일한 역할을 수행한다.

 

/MP 스위치를 켜고 빌드 -> 솔루션 다시 빌드 를 선택하여 컴파일을 진행해 보면 또 컴파일 실패가 된다.

 

msado15.tlh(5025): fatal error C1083: 포함 파일을 열 수 없습니다. "....\msado15.tli': No such file or directory"

 

하지만 컴파일 오류 내용을 잘 보면 포함 파일을 열 수 없습니다. 라고 나오는것을 알 수 있기 때문에 tlh 파일 안에서 msado15.tli 파일을 찾을 수 없다 라는 오류를 알 수 있다.

 

msado15.tlh 파일을 메모장등의 에디터로 열어보자.

 

편집 -> 찾기 메뉴를 이용하요 .tli 를 찾아 보면 거의 끝부분에서 다음 줄을 찾을 수 있다.

 

//

// Wrapper method implementations

//

#include ".......\debug\msado15.tli"

 

 

앞 경로는 개인정보 보호상 삭제..

 

Full Path 로 된 #include  문을 찾을 수 있는데 바로 이 부분의 경로가 Debug 폴더까지 들어가 있어서 파일을 찾을 수 없는것으로 나오는것이다.

 

경로를 #import 문이 있는 소스의 경로로 수정한 다음 다시 한번 컴파일 해보면

 

제대로 컴파일 되는것을 확인 할 수 있다.

 

x64 ADO import

Programming/MFC 2016. 10. 28. 16:33 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

ERROR


error C2813: /MP를 지정하면 #import를 사용할 수 없습니다. 

error C2653: 'ADODB' : 클래스 또는 네임스페이스 이름이 아닙니다.


x64 ADO import



ADO 바이너리가 두 군데 나뉘어 배포된다. x32 바이너리는 C:\Program Files (x86)\Common Files\System\ado\에 있고, x64 바이너리는 C:\Program Files\Common Files\System\ado\에 있다. 그러니 ADO를 import할 땐 이런 식으로 하면 된다.




#import "C:\Program Files\Common Files\System\ado\msado15.dll"





#import "C:\Program Files (x86)\Common Files\System\ado\msado15.dll"





#import "libid:EF53050B-882E-4776-B643-EDA472E8E3F2"






x32 x64 상관 없이 돌리려면




#if defined(WIN64)

#import "C:\Program Files\Common Files\System\ado\msado15.dll"

#else

#import "libid:EF53050B-882E-4776-B643-EDA472E8E3F2"

#endif




참조 : https://andromedarabbit.net/wp/unhappy_when_importing_x64_ado/





OpenSSL x86 Build

Programming/C,CPP,CS 2016. 10. 28. 15:39 Posted by TanSanC
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

OpenSSL x86 Build


Windows7 64bit


Visual Studio 2013






1. download openssl 

openssl-1.0.2j.tar.gz


http://openssl.org/source/





extract to D:\openssl-1.0.2j






2. download/install ActivePerl for Win64 


http://www.activestate.com/activeperl/downloads





C:\Program Files (x86)\Microsoft Visual Studio 12.0\Common7\Tools\Shortcuts


execute VS2013 x86 네이티브 도구 명령 프롬프트, VS2013 x86 Native Tools Command Prompt





change directory to D:\openssl-1.0.2j


3. Setting Target openssldir


perl Configure VC-WIN32 no-idea no-mdc2 no-rc5 --prefix=d:\openssl32bit no-shared no-asm threads



no-asm 옵션을 추가하지 않으면 nasm 을 설치하여야 하므로.....


no-idea, no-mdc2, no-rc5 옵션은 특허가 포함되어있는 모듈이므로


꼭 필요하지 않다면 사용하지 않는 것이 좋습니다.



참고 : http://greenfishblog.tistory.com/81



사진은 64비트 버전의 것을 복붙을 하여서 명령어가 다릅니다. 참고바랍니다.








4. Setting complie enviroment


ms\do_ms








5. Complie


nmake -f ms\ntdll.mak install






설치 명령어는 사실


openssl 폴더에 있는



INSTALL.W64 , INSTALL.W32 만 따라하셔도 충분히 가능합니다.








'Programming > C,CPP,CS' 카테고리의 다른 글

임계영역 설정 Ctirical Section  (0) 2016.11.07
Jsoncpp 주의 사항  (0) 2016.11.01
pjproject-2.5.5  (0) 2016.10.14
pjsip Building for Microsoft Windows  (1) 2016.10.12
oRTP  (0) 2016.10.11
336x280(권장), 300x250(권장), 250x250, 200x200 크기의 광고 코드만 넣을 수 있습니다.

Java SocketServer control Image, DBConnect, String




package com.tistory.tansanc;

import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayInputStream;
import java.io.DataInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.ServerSocket;
import java.net.Socket;
import java.sql.Connection;
import java.sql.DriverManager;
import java.sql.ResultSet;
import java.sql.Statement;
import java.util.ArrayList;

import javax.imageio.ImageIO;

class DBConnect {
	ResultSet rs = null;
	Connection conn = null;
	Statement stmt = null;
	public DBConnect() {
		try {
			String url = "jdbc:sqlserver://192.168.10.17:1433;DatabaseName=MSSQLSERVER";
			
			Class.forName("com.microsoft.sqlserver.jdbc.SQLServerDriver");
			conn = DriverManager.getConnection(url, "sa", "1234");
			stmt = conn.createStatement();
			

		} catch (Exception e) {

		}
	}

	public void finalize() {
		try {
			rs.close();
			stmt.close();
			conn.close();
		} catch (Exception e) {

		}
	}
}

class PerClientThread extends Thread {
	Socket s;
	static ArrayList socketArray = new ArrayList();
	static DBConnect dbc;
	
	public PerClientThread()
	{
		
	}
	@Override
	public void run() {
		// TODO Auto-generated method stub

		socketArray.add(s);
		BufferedReader br;

		
		try {
			br = new BufferedReader(new InputStreamReader(s.getInputStream()));
			String temp;
			while ((temp = br.readLine()) != null) {
				// DB Query
				if (temp.startsWith("select")) {
					
					try {
						dbc.rs = dbc.stmt.executeQuery("SELECT * FROM [dbo].[TESTDB]");

						while (dbc.rs.next()) {
							String field1 = dbc.rs.getString("Date");
							String field2 = dbc.rs.getString("FileName");
							System.out.println(field1);
							System.out.println(field2);

							java.sql.Blob blb = dbc.rs.getBlob("Image");
							byte[] imagebytes = blb.getBytes(0, (int) blb.length());
							BufferedImage theImage = ImageIO.read(new ByteArrayInputStream(imagebytes));

						}
					} catch (Exception e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
					temp = "SQL:" + temp;
					System.out.println(temp);
				}
				// Arduino
				else if (temp.startsWith("insert"))
				{
					
				}
				// Arduino
				else if (temp.startsWith("image"))
				{

			        int size = Integer.parseInt(br.readLine());
			        
			        DataInputStream inputStream = new DataInputStream(s.getInputStream());
			        
			        byte[] imageAr = new byte[size];
			        inputStream.read(imageAr, 0, size);

			        BufferedImage image = ImageIO.read(new ByteArrayInputStream(imageAr));

			        System.out.println("Received " + image.getHeight() + "x" + image.getWidth() + ": " + System.currentTimeMillis());
			        ImageIO.write(image, "png", new File("C:\\test2.png"));


				}
				// Arduino
				else if (temp.startsWith("to"))
				{
					
				}
				System.out.print(s.getInetAddress() + " : ");
				System.out.println(temp);
				for (int i = 0; i < socketArray.size(); i++) {
					PrintWriter os = new PrintWriter(socketArray.get(i).getOutputStream(), true);
					os.print(s.getInetAddress() + " : ");
					os.println(temp);
				}
			}

		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		super.run();
	}
}

public class Server {
	public static void main(String[] args) throws Exception {
 
		System.out.println("Server Side");
		ServerSocket ss = new ServerSocket(33333);
		Socket s;
		while (true) {
			s = ss.accept();
			PerClientThread pct = new PerClientThread();
			pct.s = s;
			pct.dbc = new DBConnect();
			pct.start();
		}

	}
}










Client.java
package com.tistory.tansanc;

import java.awt.BorderLayout;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.awt.image.BufferedImage;
import java.io.BufferedReader;
import java.io.ByteArrayOutputStream;
import java.io.DataOutputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.PrintWriter;
import java.net.Socket;

import javax.imageio.ImageIO;
import javax.swing.JFrame;
import javax.swing.JTextArea;
import javax.swing.JTextField;

class MyFrame extends JFrame {
	public static JTextArea textArea;
	JTextField textField;
	PrintWriter out;
	Socket s;

	public MyFrame() {
		textArea = new JTextArea();
		textField = new JTextField();
		add(BorderLayout.CENTER, textArea);
		add(BorderLayout.SOUTH, textField);
		textField.addActionListener(new FieldListener());
		setSize(300, 200);
		setTitle("채팅프로그램 Client");
		setVisible(true);
		// GUI를 설계한다.
	}

	class FieldListener implements ActionListener {

		@Override
		public void actionPerformed(ActionEvent e) {
			// TODO Auto-generated method stub
			if (textField.getText().compareTo("image") == 0) {

				BufferedImage image;
				ByteArrayOutputStream byteArrayOutputStream = null;
				DataOutputStream os = null;
				try {
					image = ImageIO.read(new File("C:\\test.png"));
					byteArrayOutputStream = new ByteArrayOutputStream();
					ImageIO.write(image, "png", byteArrayOutputStream);
					os = new DataOutputStream(s.getOutputStream());
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}
				
				try {
					int size = byteArrayOutputStream.size();
					out.println("image");
					out.println(size);
					os.write(byteArrayOutputStream.toByteArray());
					os.flush();
				} catch (Exception e1) {
					// TODO Auto-generated catch block
					e1.printStackTrace();
				}

			} else {
				out.println(textField.getText());
				textField.setText("");
			}
			// 메세지 보내기
		}
	}
}

class SendThread extends Thread {
	PrintWriter out;

	public SendThread(PrintWriter out) {
		this.out = out;
	}

	@Override
	public void run() {
		// TODO Auto-generated method stub
		super.run();
	}
}

class RecvThread extends Thread {
	BufferedReader in;

	public RecvThread(BufferedReader in) {
		this.in = in;
	}

	@Override
	public void run() {
		String temp;
		try {
			while ((temp = in.readLine()) != null) {

				MyFrame.textArea.setText(MyFrame.textArea.getText() + "\n" + temp);
			}
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}

class ClientModule {
	MyFrame mFrame;
	SendThread mSendThread;
	RecvThread mRecvThread;
	Socket s;

	// 서버에 패킷을 보내는 Thread
	// 서버로부터 패킷을 받는 Thread
	public ClientModule() // 준비
	{

		try {
			s = new Socket("192.168.10.17", 33333);
			PrintWriter out = new PrintWriter(s.getOutputStream(), true);
			BufferedReader in = new BufferedReader(new InputStreamReader(s.getInputStream()));
			mFrame = new MyFrame(); // GUI 객체
			mFrame.s = s;
			mFrame.out = out;
			mSendThread = new SendThread(out);
			mRecvThread = new RecvThread(in);
		} catch (Exception e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	void start() // 시작
	{
		mSendThread.start();
		mRecvThread.start();
	}
}

public class Client {
	public static void main(String[] args) {
		ClientModule cm = new ClientModule();
		// 초기화 작업
		cm.start();
		// Thread.start();
	}
}