Work/PSP
[PSP_DEV 4_2] PSP와 통신을 해보자! 클라이언트편
kevin.
2007. 1. 8. 20:49
이제 PC에 server 작업을 끝냈으니, psp에서 클라이언트를 작업해보자.
클라이언트도 사실 간단하다.
그런데 문제는 PSP의 네트웍 사용 시퀀스를 모른다는 건데.. 그건 걱정할 필요가 없다.
왜냐믄.. PSPSDK에 아주 친절하게 sample이 있으니까 ^^
소스는 두가지 부분으로 나누어 놓았습니다.
첫번째는 main 소스이고 두번째는 network 연결부분 소스입니다.
main 소스에서는 psp의 ctrl변화를 감지하는 스레드를 동작시키고, network 를 이용하여 서버로 전송하게 됩니다.
자..이제 봅시다.
/*
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* main.c - Simple elf based network example.
*
* Copyright (c) 2005 James F <tyranid@gmail.com>
* Some small parts (c) 2005 PSPPet
*
* $Id: main.c 1887 2006-05-01 03:54:06Z jim $
* $HeadURL: svn://svn.pspdev.org/psp/trunk/pspsdk/src/samples/net/simple/main.c $
* modified by CK_ONE http://story.tistory.com (2007.01.08)
*/
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pspctrl.h>
* PSP Software Development Kit - http://www.pspdev.org
* -----------------------------------------------------------------------
* Licensed under the BSD license, see LICENSE in PSPSDK root for details.
*
* main.c - Simple elf based network example.
*
* Copyright (c) 2005 James F <tyranid@gmail.com>
* Some small parts (c) 2005 PSPPet
*
* $Id: main.c 1887 2006-05-01 03:54:06Z jim $
* $HeadURL: svn://svn.pspdev.org/psp/trunk/pspsdk/src/samples/net/simple/main.c $
* modified by CK_ONE http://story.tistory.com (2007.01.08)
*/
#include <pspkernel.h>
#include <pspdebug.h>
#include <pspsdk.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>
#include <pspctrl.h>
#include "graphic.h"
#include "network.h"
#include "network.h"
#define printf pspDebugScreenPrintf
PSP_MODULE_INFO(MODULE_NAME, 0x1000, 1, 1);
PSP_MAIN_THREAD_ATTR(0);
PSP_MAIN_THREAD_ATTR(0);
/*
* 프로그램이 종료되었을 경우 thread내의 루프를 더 이상
* 돌지 않도록 하기 위해 flag를 하나 둡니다.
*/
int done = 0;
/*
* psp의 key를 전송하는 thread는 Tcp/ip 접속이 종료된 후 시작되어야
* 하기 때문에 network 모듈에서 threadStart를 call하게 됩니다.
* 이를 위해 thread의 id를 넘겨줘야 하므로 여기에 저장해 둡니다.
*/
SceUID ctrlid;
* 프로그램이 종료되었을 경우 thread내의 루프를 더 이상
* 돌지 않도록 하기 위해 flag를 하나 둡니다.
*/
int done = 0;
/*
* psp의 key를 전송하는 thread는 Tcp/ip 접속이 종료된 후 시작되어야
* 하기 때문에 network 모듈에서 threadStart를 call하게 됩니다.
* 이를 위해 thread의 id를 넘겨줘야 하므로 여기에 저장해 둡니다.
*/
SceUID ctrlid;
/*
* 서버와 연결된 소켓을 저장할 공간입니다.
* 이 소켓을 통하여 서버로 key 값을 전송합니다.
*/
int sock;
* 서버와 연결된 소켓을 저장할 공간입니다.
* 이 소켓을 통하여 서버로 key 값을 전송합니다.
*/
int sock;
/* Exit callback */
int exit_callback(int arg1, int arg2, void *common)
{
done = 1;
sceKernelExitGame();
return 0;
}
int exit_callback(int arg1, int arg2, void *common)
{
done = 1;
sceKernelExitGame();
return 0;
}
/* Callback thread */
int CallbackThread(SceSize args, void *argp)
{
int cbid;
int CallbackThread(SceSize args, void *argp)
{
int cbid;
cbid = sceKernelCreateCallback("Exit Callback", exit_callback, NULL);
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
sceKernelRegisterExitCallback(cbid);
sceKernelSleepThreadCB();
return 0;
}
}
/* Sets up the callback thread and returns its thread id */
int SetupCallbacks(void)
{
int thid = 0;
int SetupCallbacks(void)
{
int thid = 0;
thid = sceKernelCreateThread("update_thread", CallbackThread,
0x11, 0xFA0, PSP_THREAD_ATTR_USER, 0);
if(thid >= 0)
{
sceKernelStartThread(thid, 0, 0);
}
0x11, 0xFA0, PSP_THREAD_ATTR_USER, 0);
if(thid >= 0)
{
sceKernelStartThread(thid, 0, 0);
}
return thid;
}
}
/* 네트워크를 세팅하고 server에 접속합니다. */
int net_thread(SceSize args, void *argp)
{
int err;
int net_thread(SceSize args, void *argp)
{
int err;
do
{
/*
* Inet과 관련된 모듈을 초기화합니다.
*/
if((err = pspSdkInetInit()))
{
printf(MODULE_NAME ": Error, could not initialise the network %08X\n", err);
break;
}
{
/*
* Inet과 관련된 모듈을 초기화합니다.
*/
if((err = pspSdkInetInit()))
{
printf(MODULE_NAME ": Error, could not initialise the network %08X\n", err);
break;
}
/* Access point에 접속합니다. 소스는 network 모듈에 있습니다. */
if(connect_to_apctl(1))
{
// connected, get my IPADDR and run test
char szMyIPAddr[32];
/* AP의 정보를 가져옵니다. (API 설명은 없군요..) */
if (sceNetApctlGetInfo(8, szMyIPAddr) != 0)
strcpy(szMyIPAddr, "unknown IP address");
if(connect_to_apctl(1))
{
// connected, get my IPADDR and run test
char szMyIPAddr[32];
/* AP의 정보를 가져옵니다. (API 설명은 없군요..) */
if (sceNetApctlGetInfo(8, szMyIPAddr) != 0)
strcpy(szMyIPAddr, "unknown IP address");
/* 서버에 접속합니다. */
sock = connectServer(ctrlid);
}
}
while(0);
sock = connectServer(ctrlid);
}
}
while(0);
return 0;
}
}
/*
* 이 함수는 psp의 키가 눌리는 것을 계속 감시하고 있습니다.
* 만약 ctrl의 변화가 있으면 서버로 전송하고 화면에 print문을 출력합니다.
* 서버로 key를 전송하는 sendKey는 네트워크 모듈에 있습니다.
*/
int ctrl_thread(SceSize args, void *argp)
{
/*
* analog와 십자키, 버튼들의 상태를 가지고있는 데이터 구조입니다.
*/
SceCtrlData pad;
* 이 함수는 psp의 키가 눌리는 것을 계속 감시하고 있습니다.
* 만약 ctrl의 변화가 있으면 서버로 전송하고 화면에 print문을 출력합니다.
* 서버로 key를 전송하는 sendKey는 네트워크 모듈에 있습니다.
*/
int ctrl_thread(SceSize args, void *argp)
{
/*
* analog와 십자키, 버튼들의 상태를 가지고있는 데이터 구조입니다.
*/
SceCtrlData pad;
while(!done)
{
pspDebugScreenSetXY(0, 2);
{
pspDebugScreenSetXY(0, 2);
/*
* ctrl buffer를 읽어옵니다.
*/
sceCtrlReadBufferPositive(&pad, 1);
* ctrl buffer를 읽어옵니다.
*/
sceCtrlReadBufferPositive(&pad, 1);
/* analog의 좌표를 출력합니다. */
printf("Analog X = %d ", pad.Lx);
printf("Analog Y = %d \n", pad.Ly);
printf("Analog X = %d ", pad.Lx);
printf("Analog Y = %d \n", pad.Ly);
if (pad.Buttons != 0)
{
if (pad.Buttons & PSP_CTRL_SQUARE){
sendKey(sock, "SQUARE", 6);
printf("Square pressed \n");
}
if (pad.Buttons & PSP_CTRL_TRIANGLE){
sendKey(sock, "TRIANGLE", 8);
printf("Triangle pressed \n");
}
if (pad.Buttons & PSP_CTRL_CIRCLE){
sendKey(sock, "CIRCLE", 6);
printf("Cicle pressed \n");
}
if (pad.Buttons & PSP_CTRL_CROSS){
sendKey(sock, "CROSS", 5);
printf("Cross pressed \n");
}
{
if (pad.Buttons & PSP_CTRL_SQUARE){
sendKey(sock, "SQUARE", 6);
printf("Square pressed \n");
}
if (pad.Buttons & PSP_CTRL_TRIANGLE){
sendKey(sock, "TRIANGLE", 8);
printf("Triangle pressed \n");
}
if (pad.Buttons & PSP_CTRL_CIRCLE){
sendKey(sock, "CIRCLE", 6);
printf("Cicle pressed \n");
}
if (pad.Buttons & PSP_CTRL_CROSS){
sendKey(sock, "CROSS", 5);
printf("Cross pressed \n");
}
if (pad.Buttons & PSP_CTRL_UP){
sendKey(sock, "UP", 2);
printf("Up pressed \n");
}
if (pad.Buttons & PSP_CTRL_DOWN){
sendKey(sock, "DOWN", 4);
printf("Down pressed \n");
}
if (pad.Buttons & PSP_CTRL_LEFT){
sendKey(sock, "LEFT", 4);
printf("Left pressed \n");
}
if (pad.Buttons & PSP_CTRL_RIGHT){
sendKey(sock, "RIGHT", 5);
printf("Right pressed \n");
}
sendKey(sock, "UP", 2);
printf("Up pressed \n");
}
if (pad.Buttons & PSP_CTRL_DOWN){
sendKey(sock, "DOWN", 4);
printf("Down pressed \n");
}
if (pad.Buttons & PSP_CTRL_LEFT){
sendKey(sock, "LEFT", 4);
printf("Left pressed \n");
}
if (pad.Buttons & PSP_CTRL_RIGHT){
sendKey(sock, "RIGHT", 5);
printf("Right pressed \n");
}
if (pad.Buttons & PSP_CTRL_START){
sendKey(sock, "START", 5);
printf("Start pressed \n");
}
if (pad.Buttons & PSP_CTRL_SELECT){
sendKey(sock, "SELECT", 6);
printf("Select pressed \n");
}
if (pad.Buttons & PSP_CTRL_NOTE){
sendKey(sock, "NOTE", 4);
printf("Note pressed \n");
}
if (pad.Buttons & PSP_CTRL_LTRIGGER){
sendKey(sock, "LTRIGGER", 8);
printf("L-trigger pressed \n");
}
if (pad.Buttons & PSP_CTRL_RTRIGGER){
sendKey(sock, "RTRIGGER", 8);
printf("R-trigger pressed \n");
}
}
}
return 0;
}
sendKey(sock, "START", 5);
printf("Start pressed \n");
}
if (pad.Buttons & PSP_CTRL_SELECT){
sendKey(sock, "SELECT", 6);
printf("Select pressed \n");
}
if (pad.Buttons & PSP_CTRL_NOTE){
sendKey(sock, "NOTE", 4);
printf("Note pressed \n");
}
if (pad.Buttons & PSP_CTRL_LTRIGGER){
sendKey(sock, "LTRIGGER", 8);
printf("L-trigger pressed \n");
}
if (pad.Buttons & PSP_CTRL_RTRIGGER){
sendKey(sock, "RTRIGGER", 8);
printf("R-trigger pressed \n");
}
}
}
return 0;
}
/* Simple thread */
int main(int argc, char **argv)
{
SceUID thid;
int main(int argc, char **argv)
{
SceUID thid;
/* Callback을 생성하고 등록합니다. */
SetupCallbacks();
SetupCallbacks();
/* 디버그 스크린을 초기화 합니다. */
pspDebugScreenInit();
pspDebugScreenInit();
/*
* ctrl의 상태를 얻어오기 위해 관련 함수를 불러줍니다.
* 사실 무슨 일을 하는 것인지 잘 모른답니다 ^^;;
*/
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
* ctrl의 상태를 얻어오기 위해 관련 함수를 불러줍니다.
* 사실 무슨 일을 하는 것인지 잘 모른답니다 ^^;;
*/
sceCtrlSetSamplingCycle(0);
sceCtrlSetSamplingMode(PSP_CTRL_MODE_ANALOG);
/*
* Inet 관련 모듈을 로드합니다.
* Inet 관련 모듈을 로드합니다.
*/
if(pspSdkLoadInetModules() < 0)
{
printf("Error, could not load inet modules\n");
sceKernelSleepThread();
}
/* 네트워크에 접속할 thread를 생성합니다. */
thid = sceKernelCreateThread("net_thread", net_thread, 0x18, 0x10000, PSP_THREAD_ATTR_USER, NULL);
if(thid < 0)
{
printf("Error, could not create net thread\n");
sceKernelSleepThread();
}
thid = sceKernelCreateThread("net_thread", net_thread, 0x18, 0x10000, PSP_THREAD_ATTR_USER, NULL);
if(thid < 0)
{
printf("Error, could not create net thread\n");
sceKernelSleepThread();
}
/* psp의 ctrl 변화를 감지할 thread를 생성합니다. */
ctrlid = sceKernelCreateThread("ctrl_thread", ctrl_thread, 0x19, 0x10000, PSP_THREAD_ATTR_USER, NULL);
if(ctrlid < 0)
{
printf("Error, could not create ctrl thread\n");
sceKernelSleepThread();
}
ctrlid = sceKernelCreateThread("ctrl_thread", ctrl_thread, 0x19, 0x10000, PSP_THREAD_ATTR_USER, NULL);
if(ctrlid < 0)
{
printf("Error, could not create ctrl thread\n");
sceKernelSleepThread();
}
sceKernelStartThread(thid, 0, NULL);
sceKernelExitDeleteThread(0);
return 0;
}
}
#include "network.h"
#include "graphic.h"
#include "graphic.h"
// connect to server
int connectServer(SceUID ctrlid)
{
int sock;
struct sockaddr_in sockAddr;
int connectServer(SceUID ctrlid)
{
int sock;
struct sockaddr_in sockAddr;
/* 소켓을 생성합니다. */
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
printf("Error to make socket\n");
return -1;
}
printf("1/4. create socket : %d.\n", sock);
sock = socket(PF_INET, SOCK_STREAM, 0);
if(sock < 0)
{
printf("Error to make socket\n");
return -1;
}
printf("1/4. create socket : %d.\n", sock);
/* 서버의 정보를 세팅합니다. */
sockAddr.sin_family = AF_INET;
inet_pton(AF_INET, "192.168.4.108", &sockAddr.sin_addr);
sockAddr.sin_port = htons(PORT);
sockAddr.sin_family = AF_INET;
inet_pton(AF_INET, "192.168.4.108", &sockAddr.sin_addr);
sockAddr.sin_port = htons(PORT);
printf("2/4. finished information saved.\n");
/* 서버에 접속합니다. */
if(connect(sock, (struct sockaddr *) &sockAddr, sizeof(sockAddr)) != 0)
{
printf("Fail to connect server\n");
return -1;
}
printf("3/4. connected to server.\n");
if(connect(sock, (struct sockaddr *) &sockAddr, sizeof(sockAddr)) != 0)
{
printf("Fail to connect server\n");
return -1;
}
printf("3/4. connected to server.\n");
sendKey(sock, HELLO_MSG, strlen(HELLO_MSG));
printf("4/4. write hello message.\n");
printf("4/4. write hello message.\n");
/*
* 디버그 스크린을 clear 합니다.
*/
pspDebugScreenClear();
* 디버그 스크린을 clear 합니다.
*/
pspDebugScreenClear();
/* psp의 ctrl 변화를 감지할 ctrl thread를 시작합니다. */
sceKernelStartThread(ctrlid, 0, NULL);
sceKernelStartThread(ctrlid, 0, NULL);
return sock;
}
}
/* Access Point에 접속하기 위한 함수입니다. */
int connect_to_apctl(int config)
{
int err;
int stateLast = -1;
int connect_to_apctl(int config)
{
int err;
int stateLast = -1;
/* Access Point에 접속하기 위한 함수입니다. 추가정보가 없군요 ^^;; */
err = sceNetApctlConnect(config);
if (err != 0)
{
printf(MODULE_NAME ": sceNetApctlConnect returns %08X\n", err);
return 0;
}
err = sceNetApctlConnect(config);
if (err != 0)
{
printf(MODULE_NAME ": sceNetApctlConnect returns %08X\n", err);
return 0;
}
printf(MODULE_NAME ": Connecting Access point...\n");
while (1)
{
int state;
err = sceNetApctlGetState(&state);
if (err != 0)
{
printf(MODULE_NAME ": sceNetApctlGetState returns $%x\n", err);
break;
}
if (state > stateLast)
{
printf(" connection state %d of 4\n", state);
stateLast = state;
}
if (state == 4)
break; // connected with static IP
while (1)
{
int state;
err = sceNetApctlGetState(&state);
if (err != 0)
{
printf(MODULE_NAME ": sceNetApctlGetState returns $%x\n", err);
break;
}
if (state > stateLast)
{
printf(" connection state %d of 4\n", state);
stateLast = state;
}
if (state == 4)
break; // connected with static IP
// wait a little before polling again
sceKernelDelayThread(50*1000); // 50ms
}
printf(MODULE_NAME ": Connected to Access point!\n");
sceKernelDelayThread(50*1000); // 50ms
}
printf(MODULE_NAME ": Connected to Access point!\n");
if(err != 0)
{
return 0;
}
{
return 0;
}
return 1;
}
}
/* 서버로 현재 변화된 ctrl의 정보를 전송합니다. */
int sendKey(int sock, char* str, int len)
{
return write(sock, str, len);
}
int sendKey(int sock, char* str, int len)
{
return write(sock, str, len);
}
'Work > PSP' 카테고리의 다른 글
[PPO_Viewer] pre prototype (1) | 2007.01.17 |
---|---|
[PSP_DEV 5] PSP에 있는 파일을 읽고 써보자! (0) | 2007.01.09 |
[PSP_DEV 4_1] PSP와 통신을 해보자! 서버편 (0) | 2007.01.08 |
[PSP_DEV 3] Hello PSP! 한글로 써보자 (0) | 2007.01.07 |
[PSP_DEV 2] 반갑다 PSP~ Hello PSP 출력하기 (1) | 2007.01.05 |
'Work/PSP'의 다른글
- 현재글[PSP_DEV 4_2] PSP와 통신을 해보자! 클라이언트편