서버측
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <Windows.h> #include <process.h> #define BUF_SIZE 100 #define MAX_CLNT 256 unsigned WINAPI HandleClient(void* arg);//쓰레드 함수 void SendMsg(char* msg,int len);//메시지 보내는 함수 void ErrorHandling(char* msg); int clientCount=0; SOCKET clientSocks[MAX_CLNT];//클라이언트 소켓 보관용 배열 HANDLE hMutex;//뮤텍스 int main(int argc,char* argv[]){ WSADATA wsaData; SOCKET serverSock,clientSock; SOCKADDR_IN serverAddr,clientAddr; int clientAddrSize; HANDLE hThread; if(argc!=2){ printf("Usage : %s <port>\n",argv[0]); exit(1); } if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0) //윈도우 소켓을 사용하겠다는 사실을 운영체제에 전달 ErrorHandling("WSAStartup() error!"); hMutex=CreateMutex(NULL,FALSE,NULL);//하나의 뮤텍스를 생성한다. serverSock=socket(PF_INET,SOCK_STREAM,0); //하나의 소켓을 생성한다. memset(&serverAddr,0,sizeof(serverAddr)); serverAddr.sin_family=AF_INET; serverAddr.sin_addr.s_addr=htonl(INADDR_ANY); serverAddr.sin_port=htons(atoi(argv[1])); if(bind(serverSock,(SOCKADDR*)&serverAddr,sizeof(serverAddr))==SOCKET_ERROR) //생성한 소켓을 배치한다. ErrorHandling("bind() error"); if(listen(serverSock,5)==SOCKET_ERROR)//소켓을 준비상태에 둔다. ErrorHandling("listen() error"); while(1){ clientAddrSize=sizeof(clientAddr); clientSock=accept(serverSock,(SOCKADDR*)&clientAddr,&clientAddrSize);//서버에게 전달된 클라이언트 소켓을 clientSock에 전달 WaitForSingleObject(hMutex,INFINITE);//뮤텍스 실행 clientSocks[clientCount++]=clientSock;//클라이언트 소켓배열에 방금 가져온 소켓 주소를 전달 ReleaseMutex(hMutex);//뮤텍스 중지 hThread=(HANDLE)_beginthreadex(NULL,0,HandleClient,(void*)&clientSock,0,NULL);//HandleClient 쓰레드 실행, clientSock을 매개변수로 전달 printf("Connected Client IP : %s\n",inet_ntoa(clientAddr.sin_addr)); } closesocket(serverSock);//생성한 소켓을 끈다. WSACleanup();//윈도우 소켓을 종료하겠다는 사실을 운영체제에 전달 return 0; } unsigned WINAPI HandleClient(void* arg){ SOCKET clientSock=*((SOCKET*)arg); //매개변수로받은 클라이언트 소켓을 전달 int strLen=0,i; char msg[BUF_SIZE]; while((strLen=recv(clientSock,msg,sizeof(msg),0))!=0) //클라이언트로부터 메시지를 받을때까지 기다린다. SendMsg(msg,strLen);//SendMsg에 받은 메시지를 전달한다. //이 줄을 실행한다는 것은 해당 클라이언트가 나갔다는 사실임 따라서 해당 클라이언트를 배열에서 제거해줘야함 WaitForSingleObject(hMutex,INFINITE);//뮤텍스 실행 for(i=0;i<clientCount;i++){//배열의 갯수만큼 if(clientSock==clientSocks[i]){//만약 현재 clientSock값이 배열의 값과 같다면 while(i++<clientCount-1)//클라이언트 개수 만큼 clientSocks[i]=clientSocks[i+1];//앞으로 땡긴다. break; } } clientCount--;//클라이언트 개수 하나 감소 ReleaseMutex(hMutex);//뮤텍스 중지 closesocket(clientSock);//소켓을 종료한다. return 0; } void SendMsg(char* msg,int len){ //메시지를 모든 클라이언트에게 보낸다. int i; WaitForSingleObject(hMutex,INFINITE);//뮤텍스 실행 for(i=0;i<clientCount;i++)//클라이언트 개수만큼 send(clientSocks[i],msg,len,0);//클라이언트들에게 메시지를 전달한다. ReleaseMutex(hMutex);//뮤텍스 중지 } void ErrorHandling(char* msg){ fputs(msg,stderr); fputc('\n',stderr); exit(1); } | cs |
클라이언트 측
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 | #include <stdio.h> #include <stdlib.h> #include <string.h> #include <Windows.h> #include <process.h> #define BUF_SIZE 100 #define NAME_SIZE 20 unsigned WINAPI SendMsg(void* arg);//쓰레드 전송함수 unsigned WINAPI RecvMsg(void* arg);//쓰레드 수신함수 void ErrorHandling(char* msg); char name[NAME_SIZE]="[DEFAULT]"; char msg[BUF_SIZE]; int main(int argc,char* argv[]){ WSADATA wsaData; SOCKET sock; SOCKADDR_IN serverAddr; HANDLE sendThread,recvThread; if(argc!=4){ printf("Usage : %s <IP> <port> <name>\n",argv[0]); exit(1); } if(WSAStartup(MAKEWORD(2,2),&wsaData)!=0)// 윈도우 소켓을 사용한다고 운영체제에 알림 ErrorHandling("WSAStartup() error!"); sprintf(name,"[%s]",argv[3]); sock=socket(PF_INET,SOCK_STREAM,0);//소켓을 하나 생성한다. memset(&serverAddr,0,sizeof(serverAddr)); serverAddr.sin_family=AF_INET; serverAddr.sin_addr.s_addr=inet_addr(argv[1]); serverAddr.sin_port=htons(atoi(argv[2])); if(connect(sock,(SOCKADDR*)&serverAddr,sizeof(serverAddr))==SOCKET_ERROR)//서버에 접속한다. ErrorHandling("connect() error"); //접속에 성공하면 이 줄 아래가 실행된다. sendThread=(HANDLE)_beginthreadex(NULL,0,SendMsg,(void*)&sock,0,NULL);//메시지 전송용 쓰레드가 실행된다. recvThread=(HANDLE)_beginthreadex(NULL,0,RecvMsg,(void*)&sock,0,NULL);//메시지 수신용 쓰레드가 실행된다. WaitForSingleObject(sendThread,INFINITE);//전송용 쓰레드가 중지될때까지 기다린다./ WaitForSingleObject(recvThread,INFINITE);//수신용 쓰레드가 중지될때까지 기다린다. //클라이언트가 종료를 시도한다면 이줄 아래가 실행된다. closesocket(sock);//소켓을 종료한다. WSACleanup();//윈도우 소켓 사용중지를 운영체제에 알린다. return 0; } unsigned WINAPI SendMsg(void* arg){//전송용 쓰레드함수 SOCKET sock=*((SOCKET*)arg);//서버용 소켓을 전달한다. char nameMsg[NAME_SIZE+BUF_SIZE]; while(1){//반복 fgets(msg,BUF_SIZE,stdin);//입력을 받는다. if(!strcmp(msg,"q\n")||!strcmp(msg,"Q\n")){//q를 입력하면 종료한다. closesocket(sock); exit(0); } sprintf(nameMsg,"%s %s",name,msg);//nameMsg에 메시지를 전달한다. send(sock,nameMsg,strlen(nameMsg),0);//nameMsg를 서버에게 전송한다. } return 0; } unsigned WINAPI RecvMsg(void* arg){ SOCKET sock=*((SOCKET*)arg);//서버용 소켓을 전달한다. char nameMsg[NAME_SIZE+BUF_SIZE]; int strLen; while(1){//반복 strLen=recv(sock,nameMsg,NAME_SIZE+BUF_SIZE-1,0);//서버로부터 메시지를 수신한다. if(strLen==-1) return -1; nameMsg[strLen]=0;//문자열의 끝을 알리기 위해 설정 fputs(nameMsg,stdout);//자신의 콘솔에 받은 메시지를 출력한다. } return 0; } void ErrorHandling(char* msg){ fputs(msg,stderr); fputc('\n',stderr); exit(1); } | cs |
'컴퓨터 공학' 카테고리의 다른 글
윈도우 10에서 오큘러스 리프트 런타임 동작하지 않을 때. (0) | 2015.11.27 |
---|---|
[퍼옴]초보자를 위한 A* 알고리즘 (기초개념 설명 및 소스) (0) | 2015.11.27 |
[뉴스]Qt, ‘Qt5.5’ 제공 윈도10 지원…블루투스 저에너지 기능 추가 (0) | 2015.11.27 |
[자바] jar파일을 exe파일로 변환하기 (JSmooth) (2) | 2015.11.27 |
C# 궁금증 해결 리스트 (0) | 2015.11.27 |