네트워크 non-blocking server 3명 접속 받기
// nonblocking_server.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include <winsock2.h> //windows.h보다 먼저 선언해야함
#include <windows.h>
#include <process.h>
#include <stdlib.h>
#include <iostream>
#define BUFSIZE 512
unsigned int WINAPI ServerProc(LPVOID lpParam);
unsigned int WINAPI ClientContorl(LPVOID lpParam);
SOCKET gsock[3];//client sock 정보 저장
int sock_count=0;
int main(int argc, char* argv[])
{
DWORD dwID;
HANDLE h = (HANDLE)_beginthreadex(NULL, 0, ServerProc, NULL, 0, (unsigned *)&dwID); //스레드 생성
WaitForSingleObject(h,INFINITE); //스레드 종료를 기다림
printf("Main Thread 종료\n");
CloseHandle(h); //핸들을 반환
return 0;
}
unsigned int WINAPI ServerProc(LPVOID lpParam)
{
WSADATA wsa;
int retval;
//윈속 초기화
if(WSAStartup(MAKEWORD(2,2),&wsa) !=0)
return -1;
SOCKET listen_sock = socket(AF_INET,SOCK_STREAM,0);
if(listen_sock == INVALID_SOCKET)
printf("소켓 초기화 실패\n");
//---------------넌 블록킹 소켓으로 전환--------
u_long on =1;
retval = ioctlsocket(listen_sock,FIONBIO,&on);
if(retval==SOCKET_ERROR)
{
printf("소켓 속성 변경 실패\n");
return 0;
}
//----------------------------------------------
SOCKADDR_IN serveraddr;
ZeroMemory(&serveraddr,sizeof(serveraddr));
serveraddr.sin_family= AF_INET;
serveraddr.sin_port=htons(9000);
serveraddr.sin_addr.s_addr=htonl(INADDR_ANY);
//bind 서버의 지역 IP주소와 지역 포트번호를 결정
//(클라이언트의 접속을 수용할 소켓,이변수늬 주소와 지역포트 번호로 초기화 시킴,소켓주소 구조체변수의 길이)
retval=bind(listen_sock,(SOCKADDR*)&serveraddr,sizeof(serveraddr));
if(retval==SOCKET_ERROR)
printf("bind error\n");
//listen
//client의 접속을 받아들일수 있는 상태로 포트 상태를 변경한다.
retval=listen(listen_sock,SOMAXCONN);
if(retval==SOCKET_ERROR)
printf("listen error\n");
SOCKET client_sock;
SOCKADDR_IN clientaddr;
int addrlen;
HANDLE hThread;
DWORD THreadID;
//accept()
addrlen = sizeof(clientaddr);
//클라이언트에서 접근을 하면 연결을 허락해준다.
//(소켓 서버, 클라이언트의 주소(sockaddr 타입), 클라이언트 주소의사이즈)
printf("client 접속대기\n");
Sleep(1000);
while(sock_count<3)
{
//printf("client 접속대기\n");
client_sock = accept(listen_sock,(SOCKADDR *)&clientaddr,&addrlen);
if(client_sock ==INVALID_SOCKET)
{ //WSAEWOULDBLOCK이란 읽을려고 하는데 첫번째 데이터가 없을때 발생이 된다.
//즉 NonBlocking 모드에서는 자주 발생할수 밖에 없는 에러이다.
if(WSAGetLastError()!=WSAEWOULDBLOCK)
printf("accept error\n");
}
else
{
gsock[sock_count]=client_sock;
printf("client 접속자 : %d 명\n",sock_count+1);
printf("[TCP 서버]클라이언트 접속: IP 주소=%s, 포트번호 %d\n",\
inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
sock_count++;
if(sock_count==1){
hThread = (HANDLE)_beginthreadex(NULL, 0, ClientContorl,(LPVOID)client_sock, 0, (unsigned *)&THreadID); //스레드 생성
}
}
Sleep(500);
}
if(hThread==NULL)
printf("Client Thread Error\n");
WaitForSingleObject(hThread,INFINITE); //스레드 종료를 기다림
printf("server thread 종료\n");
CloseHandle(hThread);
closesocket(listen_sock);
WSACleanup(); //윈속 종료
return 0;
}
unsigned int WINAPI ClientContorl(LPVOID lpParam)//클라이언트 접속시 데이타 처리부분
{
char buf[BUFSIZE+1];
SOCKADDR_IN clientaddr;
int addrlen;
int retval;
// client 정보 얻기
while(1)
{
if(sock_count==0)
break;
//데이타 받기
printf("데이타 수신 대기\n");
Sleep(500);
for(int i=sock_count-1; i>=0; i--)
{
retval = recv(gsock[i], buf, BUFSIZE, 0 );
if(retval == SOCKET_ERROR)
{
int error;
error=WSAGetLastError();
if(error==WSAECONNRESET)//소켓종료 메시지
{
for(int num=i; num<sock_count; num++)
{
addrlen = sizeof( gsock[num]);
getpeername( gsock[num],(SOCKADDR *)&clientaddr,&addrlen);
closesocket( gsock[num]);
printf("ClientContorl 종료 [TCP서버]:IP 주소:%s, 포트번호=%d\n"\
,inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port));
if(num==2)
{
break;
}
gsock[num] = gsock[num+1];
}
sock_count--;
break;
}
else if(error!=WSAEWOULDBLOCK)
{
printf("데이타 받기 실패!");
break;
}
}
else if(retval ==0)
{
break;
}
else
{
//데이터 출력
buf[retval]='\0';
printf("[TCP/%s:%d] %s\n",inet_ntoa(clientaddr.sin_addr),ntohs(clientaddr.sin_port),buf);
//데이터 보내기
retval = send(gsock[i], buf, retval, 0);
if(retval==SOCKET_ERROR)
{
printf("recv error!\n");
break;
}
}
}
}
printf("server 종료....\n");
return 0;
}
-AVR 스탑워치-
포즈 기능과 리셋기능(포즈 기능 까지만 완료)
#include <avr/io.h>
#include <avr/signal.h>
#include <avr/interrupt.h>
volatile unsigned int g_elapsed_time;
volatile unsigned char c;
void initLED(void);
void initFND(void);
void setTCCR0(void);
void initTCNT0(void);
void setTIMSK(void);
void FNDLED(void);
void sleep(unsigned int elapsed_time);
SIGNAL(SIG_OUTPUT_COMPARE0);
int main(void)
{
initLED();
initFND();
setTCCR0();
initTCNT0();
setTIMSK();
sei();
while(1)
{
FNDLED();
}
return 1;
}
void FNDLED(void)
{
volatile unsigned char a;
volatile unsigned char b;
volatile unsigned char c;
for(b=1;;b++)
{
for(a=0;a<=153;a++)
{
c=PINC;
if(a%16>9)
{
a=a+6;
}
if(~c&1<<0==1)
{
for(;;)
{
sleep(10);
c=PINC;
if(~c&1<<0==1)
{
break;
}
}
}
sleep(10);
PORTE=a;
}
PORTF=~b;
}
}
void initFND(void)
{
DDRE=0xff;
PORTE=0x00;
}
void initLED(void)
{
DDRF = 0xFF;
PORTF = 0xFF;
}
void setTCCR0(void)
{
TCCR0|=4;
TCCR0|=8;
}
void initTCNT0(void)
{
OCR0=250;
TCNT0=0;
}
void setTIMSK(void)
{
TIMSK=2;
}
void sleep(unsigned int elapsed_time)
{
g_elapsed_time=0;
while(g_elapsed_time<elapsed_time)
{
}
}
SIGNAL(SIG_OUTPUT_COMPARE0)
{
g_elapsed_time++;
}
-포즈 기능에서 빠른 제어 속도로 인해
if(~c&1<<0==1)
{
for(;;)
{
sleep(10);
c=PINC;
if(~c&1<<0==1)
{
위 소스 처럼 슬립함수를 이용해서 딜레이를 줘야 하는 문제가 발생
딜레이를 주다 보니 그 함수로 인해 같은 스위치로 제어하는 포즈기능이 제대로 즉각즉각 반응 하지 않는 문제 발생
----> 같은 스위치로 제어하기 보다 멈춤과 재동작을 나눠서 다른 스위치로 제어 하면 문제점이 고쳐짐.
'코스웨어 > 10년 시스템제어' 카테고리의 다른 글
[시스템제어] 4월 23일 수업 일지 보고서 - 22번 임 훈 (1) | 2010.04.26 |
---|---|
[시스템제어]4월 21일 일일업무 이창민(20번) (1) | 2010.04.26 |
[시스템제어]4월22일 보고서 임창모 (1) | 2010.04.22 |
[시스템제어]4월20일 보고서 19번 이상은 (1) | 2010.04.20 |
[시스템제어] 4월 15일 17번 유성민 (1) | 2010.04.15 |
[시스템제어]4월13일 (15번 신관식) 업무 보고서 (1) | 2010.04.15 |
시스템제어 - 4월14일 안태민(16번) (1) | 2010.04.14 |
시스템제어 4월12일 14번 선동환 보고서 (1) | 2010.04.12 |