#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys.socket.h>
#include <sys/time.h> // timeval {tv.sec; tv.usec; }를 사용하기 위하여 쓴다
#include <sys/select.h> // FD_ISSET FD_CLR FD_SET FD_ZERO를 사용하기 위하여 쓴다
//모든 크기를 정해놓고 시작하자
#define BUF_SIZE 1024
#define NAME_SIZE 256
//불러올 함수이다
void * void_send_Data(void * Mysocket_input);// 전송용
void * void_recv_Data(void * Mysocket_input);// 받기용
//전역 변수이다
char MyName[NAME_SIZE] // 이녀석 이름
char UName[NAME_SIZE] // 보내는 여석 이름
char InputData[BUF_SIZE] // 보낼거 입력한 싸이즈
char RecvData[BUF_SIZE] // 받을놈 싸이즈
//메인함수이다
int main(int inputcount, char *inputdata[])
{
int MySocket; // 나의 소켓
struct sockaddr_in GoTo_addr; // sockaddr_in 형식의 변수이름 clnt_addr 만듬
pthread_t snd_thread; // 전송용 쓰레드 생성
pthread_t rcv_thread; // 받기용 쓰레드 생성
void * snd_thread_return; // 전송용 쓰레드 리턴
void * rcv_thread_return; // 수신용 쓰레드 리
if(inputcount!=4) { //접속이 잘됫는지 확인하여 실행여부 판단
printf("Usage : %s <IP> <port> <name>\n" , argv[0]);
exit(1);
}
MySocket=socket(PF_INET, SOCKSTREAM, 0); //새로 생성된 내 소켓
memset(&clnt_addr, 0, sizeof(clnt_addr)); // clnt_addr의 방마다 크기에 맞게 초기화
GoTo_addr.sin_family=AF_INET; // 주소 형식을 인터넷으로 설정함
GoTo_addr.sin_addr.s_addr=inet_addr(inputdata[1]); // Server IP를 작성하여 보낼곳을 정한다
GoTo_addr.sin_port=htons(atoi(inputdata[2]));// Server Port를 작성하여 보낼곳을 정한다
if(connect(MySocket, (struct sockaddr*)&GoTo_addr, sizeof(GoTo_addr))==-1) //소켓이 잘만들어 졌나 확인 (inputdata[]배열의 하나가 더 생기고 거기에 소켓이 들어감)
error_handling("connect() error");
/////////////닉네임 전송 /////////////
sprintf(MyName, "%s",inputdata[3]); // 받은 이름을 저장함
write(MySocket, MyName, Name_SIZE); // write는 Null이 안나오면 읽었던 곳까지 읽고 킵해놓는다write(생성된 소켓 정보, 닉네임 데이터, 사이즈를 정해줌 )
////////////전송 끝//////////////////
print("\n\nCONNECTING...\n[Help] If you want \"Help\" -> /Help\n") //헬프 메뉴얼 설명을 만든다
pthread_create(&snd_thread, NULL, void_send_Data, (void*)&MySocket); // 전송용 쓰레드를 함수 void_send_Data 에 MySocket의 정보를 넣어 생성한다(실행도한다)
pthread_create(&rcv_thread, NULL, void_recv_Data, (void*)&MySocket); // 수신용 쓰레드를 함수 void_send_Data 에 MySocket의 정보를 넣어 생성한다(실행도한다)
pthread_join(snd_thread, &snd_thread_return); // 전송 쓰레드가 종료되는것을 기다린다
pthread_join(rcv_thread, &rcv_thread_return); // 수신 쓰레드가 종료되는것을 기다린다
close(MySocket); // 소켓을 닫는다
return 0; //실행되면 0값 돌려
}
// send_Data 함수이다
void * void_send_Data(void * Mysocket_input) // 전송용 쓰줌레드 함
{
// 필요한 변수들
int * MySocket = (int*)Mysocket_input; // 쏘켓의 주소를 int형으로 다시 받아온다
// 필요한 FD들
int restart; // Select에 사용할 정수 0이면 반복
fd_set FDinput, NextFDinput; // 전송받은 파일의 번호수 나 이름을 기역하기 위해서
struct timeval TimeSleepValue; // 타임슬립 구조체를 가져와 사용하기위해
char RealSend[NAME_SIZE + BUF_SIZE + 2]; //특정 명령어를 확인하기 위하여
while (1) // 계속 실행하기위해서
{
/////////////// 1초동안 입력없을시 계속 실행 ///////////////
FD_ZERO(&FDinput); // FD의 값을 0으로 초기화 한다
FD_SET(STDIN_FILENO, &FDinput); //SYDIN_FILENO 파일번호를 받아 FDinput에 적어넣는다
while (1) {
memset(InputData, 0, sizeof(InputData)); //InputData 0으로 초기화
TimeSleepValue.tv_sec = 1; //타임 1초 설정
TimeSleepValue.tv_usec = 0; //타임 유니세크(초보다작은거) 0 설정
NextFDinput = FDinput // 다음 FD를STDIN_FILENO 상태로 만들어줌
restart = select(STDIN_FILENO + 1, &NextFDinput, NULL, NULL, &TimeSleepValue); // select(파일의 순번을 받는다, 파일의 번호를 받는다?? , 읽기쓰기타입, , 슬립할 타임설정);
//FD를
/////////////// 1초동안 입력없을시 계속 실행 .////////
if (FD_ISSET(STDIN_FILENO, &NextFDinput)) // FD_ISSET(여기는 입력[이거 사용하는사람의 입력]이 있으면 숫자로 반환된다 , 여기는 입력이 없으면 제한시간을 넘으면 FALSE로 반환한다 즉 2조건을 다 확인하는 방식으로 진행이된다
{
fgets(InputData, BUF_SIZE, stdin) //stdin 전송받은 값이 여기있다 아마 컴퓨터 내장에 있는거 같다 그것을 BUF_SIZE 만한 크기에 맞게 짤라서 ecvData에 넣어준다 다 받지 못하면 아마 반복되는거같다
if (!strncmp(InputData, "quit\n", 5)) //문자를 비교한 다 비교한 것에 quit\n 이 있을 경우 전송을 중단한다 quit\n 가5글자여서 5만 비교한거 같음
{
*Mysocket = -1; //소켓을 삭제하고 메인으로 돌아간다
return NULL; //끝났기때문에 반복하지않는다
}
else if (InputData[0] != '[') //(RecvData[0]) 여기가 이제부터 비교문장이다 RecvData[0] 이기때문에 하나만 비교하는 구문이 되어있다 이거 else 로 나중에 수정하고 다 ALLmsg로 바꾸는 식으로 해야겟다
{
strcat(RealSend, "[ALLMSG]"); //명렁어 str 에 ALLMSG를 첫번쩨이 추가한다
strcat(RealSend, InputData); //입력한 데이터를 진짜 보넬 문자에 합쳐준다
}
else {
strcpy(RealSend, InputData); // 입력란에 [ 이있으면 명령어가 있는 것이니 그대로 출력한다
}
if (write(*Mysocket, RealSend, strlen(RealSend)) <= 0) //write 값이 에러이면
{
*Mysocket = -1; // 소켓 없에기
return NULL;
}
}
if (restart == 0) // 재시작이 문제가 있으면
{
if (*Mysocket == -1) //소켓이 에러 가 있으면
{
return NULL; // 널값 반환
}
}
}
}
}
void * void_recv_Data(void * Mysocket_input)
{
int * Mysocket = (int *)Mysocket_input; //입력한 소켓 정보 가져오기
char * pTocken; //잠시 나눈거 맏을예
char * split_Data[]; //받은 메세지
char get_Data[NAME_SIZE + BUF_SIZE + 1];
int get_Data_length
while (1)
{
memset(get_Data, 0x0, sizeof(get_Data));
get_Data_length = read(*Mysocket, get_Data, NAME_SIZE + BUF_SIZE);
if (get_Data_length <= 0)
{
*Mysocket = -1;
return NULL;
}
get_Data[get_Data_length] = 0;
fputs(get_Data, stdout);
pToken = strtock(name_msg, "[@]");
i = 0;
while (pTocken != NULL)
{
pArray[i] = pToken;
if (i++ >= MAX_SPLIT)
break;
pTocken = strtok(NULL, "[@]");
}
for (int i = 0 ; i < split_Data.length())
}
}
void error_handling(char * msg)
{
fputs(msg, stderr);
fputc('\n', stderr);
exit(1);
}
'[ 충남인력개발원 ] (2019) > ┗TCP&IP' 카테고리의 다른 글
통신 TCP 코드 자료 (0) | 2020.04.07 |
---|---|
Ubutu 설명페이지 한글 MAN_PAGE KO (0) | 2020.01.15 |
파일 비교하기 프로그램 (0) | 2020.01.14 |
Fgets Select(FD) 에 관하여 (0) | 2020.01.13 |
Uduntu window 통신 (0) | 2020.01.13 |