파일열기

데이터를 읽거나 쓰기 위해서 파일을 열때 사용하는 함수이다.

두개의 인자를 전달 받는데, 첫번째 인자로 대상이되는 파일의 이름 및 경로 정보, 두번째 인자로는 파일의 오픈모드정보(파일의 특성 정보)를 전달한다.

 

#include<sys/types.h>

#include<sys/stat.h>

#include<fcntl.h>


1. int open(const char *path, int flag);

path 파일 이름을 나타내는 문자열의 주소 값 전달

flag 파일의 오픈 모드 정보 전달

 성공 시 파일 디스크립터, 실패 시 -1 반환

 


 

 오픈모드

의미 

 O_CREAT 

필요하면 파일을 생성 

 O_TRUNC

기존 데이터 전부 삭제

 O_APPEND

 기존 데이터 보존하고, 뒤에 이어서 저장

 O_RDONLY

 읽기 전용으로 파일 오픈

 O_WRONLY

 쓰기 전용으로 파일 오픈

 O_RDWR

 읽기, 쓰기 겸용으로 파일오픈

 

 

파일닫기

#include<unistd.h>

2. int close(int fd);

fd 닫고자 하는 파일 또는 소켓의 파일 디스크립터 전달

 성공시 0, 실패 시 -1 반환

 


 

파일에 데이터 쓰기

파일에 데이터를 출력(전송)하는 함수이다.

 

#include<unistd.h>

3. ssize_t write(int fd, const void * buf, size_t nbytes);

fd 데이터 전송대상을 나타내는 파일 디스크립터 전달

buf 전송할 데이터가 저장된 버퍼의주소 값 전달

nbytes 전송할 데이터의 바이트 수 전달

성공 시 전달한 바이트 수, 실패시 -1 반환


4. sszie_t read(int fd, void *buf, size_t nbytes);

fd 데이터 수신대상을 나타내는 파일 디스크립터

buf 수신한 데이터를 저장할 버퍼의 주소값 전달

nbytes 수신할 최대 바이트 수 전달

 성공시 수신한 바이트수(단 파일의 끝을 만나면 0), 실패시 -1 반환


 

 

 

블로그 이미지

왕왕왕왕

,
  int   server_socket;
   int   client_socket;
   int   client_addr_size;

   struct sockaddr_in   server_addr;
   struct sockaddr_in   client_addr;

   char   buff_rcv[BUFF_SIZE+5];
   char   buff_snd[BUFF_SIZE+5];




1. int socket(int domain, int type, int protocol);

domain 

  • PF_INET, AF_INET : IPv4인터넷 프로토콜을 사용
  • PF_INET6 : IPv6인터넷 프로토콜을 사용
  • PF_LOCAL, AF_UNIX : 같으 시스템 내에서 프로세스끼리 통신합니다.
  • PF_PACKET : Low level socket 을 인터페이스를 이용
  • PF_IPX : IPX 노벨 프로토콜을 사용
type
  • SOCK_STREAM : TCP/IP 프로토콜을 이용 
  • SOCK_DGRAM : UDP/IP 프로토콜을 이용
protocol : 통신에 있어 특정 프로토콜을 사용을 지정하기 위한 변수 ,보통 0값을 사용

성공 시 파일 디스크립터, 실패 시 -1 반환

 server_socket  = socket( PF_INET, SOCK_STREAM, 0);
   if( -1 == server_socket)
   {
      printf( "server socket 생성 실패\n");
      exit( 1);
   }

 



2. int bind(int sockfd,(struct sockaddr *)&myaddr, socklen_t addrlen);

  • sockfd : 소켓 디스크립터
  • sockaddr *myaddr : 주소 정보로 인터넷을 이용하는 AF_INET인지 시스템 내에서                              통신하는  AF_UNIX에 따라서 달라집니다. 

                                 인터넷을 통해 통신하는 AF_INET인 경우에는 struct sockaddr_in을                                  사용합니다.

  • socklen_t addrlen : myadd 구조체의 크기 ex) size(sock_addr)

성공 시 0 , 실패 시 -1 반환

 if( -1 == bind( server_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
   {
      printf( "bind() 실행 에러\n");
      exit( 1);
   }

주소정보의 표현 (sockaddr/ sockaddr_in)

  • sockaddr : 소켓주소를 표현하는 구조체 
TCP/IP만을 목적으로 만들어진 것이 아니기 때문에, 다양한 주소체계에 맞게 범용 목적으로 사용하기 위해이런 단순한 구조를 가지고있다.

struct sockaddr{
sa_family_t sa_family ; 소켓 주소체계
char          sa_data[4]; 해당 주소체계에서 사용하는 주소정보

  • sockaddr_in : IPv4 주소체계에서 사용하는 구조체
소켓 프로그램은 범용 주소 구조체로 sockaddr을 사용하지만, 주소체계의 종류에 따라 별도의 전용 구조체를 만들어 사용하는게 편리하다.

struct sockaddr_in {
sin_family_t         sin_family; IPv4주소 체계에서 사용하므로 항상 AF_INET으로 설정
unist16_t             sin_port; 포트번호
struct     in_addr  sin_addr; IP주소를 나타내는 32비트 정수 타입구조체
char                   sin_zero[8]; sockaddr과 같은 크기를 유지하기 위해 필요한                                                     패딩공간. 항상 0

struct in_addr {
unit32_t              s_addr; 32비트 IPv4 인터넷 주소
}


sin_family : 주소체계(AF_INET / AF_INET6 / AF_LOCAL)

sin_port : 16비트 포트정보

sin_addr : 32비트 IP정보

sin_zero : 사용되지 않는 필드








3. int listen(int sockfd, int backlog);

  • sockfd : 소켓 디스크립터
  • backlog : 대기 메시지 큐의 개수

성공시 0, 실패 시 -1 반환

  if( -1 == listen(server_socket, 5))
   {
      printf( "listen() 실행 실패\n");
      exit( 1);
   }


 

4. int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

  • sockfd : 소켓 디스크립터
  • sockaddr *addr : 클라이언트 주소정보를 가지고 있는 포인터
  • socklen_t addrlen : struct sockaddr *addr 포인터가 가르키는 구조체의 크기

성공 시 파일 디스크립터, 실패 시 -1 반환

while( 1) { client_addr_size = sizeof( client_addr); client_socket = accept( server_socket, (struct sockaddr*)&client_addr, &client_addr_size); if ( -1 == client_socket) { printf( "클라이언트 연결 수락 실패\n"); exit( 1); }

 



5. int connect(int sockfd,struct sockaddr * serv_addr, socklen_t addrlen);

  • sockfd : 소켓 디스크립터
  • sockaddr *serv_addr : 서버 주소 정보에 대한 포인터
  • socklen_t addrlen : struct sockaddr *serv_addr 포인터 가르키는 구조체의 크기

성공시 0, 실패 시 -1 반환

  if( -1 == connect( client_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
   {
      printf( "접속 실패\n");
      exit( 1);
   }

 

 


TCP/IP 통신 함수 사용순서




서버프로그램 예제

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#define  BUFF_SIZE   1024

int   main( void)
{
   int   server_socket;
   int   client_socket;
   int   client_addr_size;

   struct sockaddr_in   server_addr;
   struct sockaddr_in   client_addr;

   char   buff_rcv[BUFF_SIZE+5];
   char   buff_snd[BUFF_SIZE+5];



   server_socket  = socket( PF_INET, SOCK_STREAM, 0);
   if( -1 == server_socket)
   {
      printf( "server socket 생성 실패\n");
      exit( 1);
   }

   memset( &server_addr, 0, sizeof( server_addr));
   server_addr.sin_family     = AF_INET;
   server_addr.sin_port       = htons( 4000);
   server_addr.sin_addr.s_addr= htonl( INADDR_ANY);

   if( -1 == bind( server_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
   {
      printf( "bind() 실행 에러\n");
      exit( 1);
   }

   if( -1 == listen(server_socket, 5))
   {
      printf( "listen() 실행 실패\n");
      exit( 1);
   }

   while( 1)
   {
      client_addr_size  = sizeof( client_addr);
      client_socket     = accept( server_socket, (struct sockaddr*)&client_addr, &client_addr_size);

      if ( -1 == client_socket)
      {
         printf( "클라이언트 연결 수락 실패\n");
         exit( 1);
      }

      read ( client_socket, buff_rcv, BUFF_SIZE);
      printf( "receive: %s\n", buff_rcv);
      
      sprintf( buff_snd, "%d : %s", strlen( buff_rcv), buff_rcv);
      write( client_socket, buff_snd, strlen( buff_snd)+1);          // +1: NULL까지 포함해서 전송
      close( client_socket);
   }
}

 클라이언트 프로그램 예제

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/types.h>
#include <sys/socket.h>

#define  BUFF_SIZE   1024

int   main( int argc, char **argv)
{
   int   client_socket;

   struct sockaddr_in   server_addr;

   char   buff[BUFF_SIZE+5];

   client_socket  = socket( PF_INET, SOCK_STREAM, 0);
   if( -1 == client_socket)
   {
      printf( "socket 생성 실패\n");
      exit( 1);
   }

   memset( &server_addr, 0, sizeof( server_addr));
   server_addr.sin_family     = AF_INET;
   server_addr.sin_port       = htons( 4000);
   server_addr.sin_addr.s_addr= inet_addr( "127.0.0.1");

   if( -1 == connect( client_socket, (struct sockaddr*)&server_addr, sizeof( server_addr) ) )
   {
      printf( "접속 실패\n");
      exit( 1);
   }
   write( client_socket, argv[1], strlen( argv[1])+1);      // +1: NULL까지 포함해서 전송
   read ( client_socket, buff, BUFF_SIZE);
   printf( "%s\n", buff);
   close( client_socket);
   
   return 0;
}


블로그 이미지

왕왕왕왕

,

 

http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html

위에 주소로 들어가서 pscp.exe를 다운받는다.

 

 

cmd로 pscp가 설치된 경로로 들어가서

 

pscp 보낼파일경로 상대방서버이름@상대방서버아이피:/전송할 경로

 

putty나 pscp나 설치할게없어서 다운받으면 그자리가 설치경로로 이해하면 된다.

블로그 이미지

왕왕왕왕

,

_beginthreadex() 사용시 에러 해결

 

비주얼 6.0에서는 라이브러리 기본 상태가 단일 스레드로 설정되있기때문에 에러가 난다.

 

Project - setting

 

 

 

블로그 이미지

왕왕왕왕

,

servAddr.sin_port = htons(atoi(servPORT));

 

소켓 프로그래밍중 위에 같이 사용하면 warning이 발생.

 

warning C4761: integral size mismatch in argument; conversion supplied

 

atoi는 리턴값이 int이나 servAddr.sin_port 는 uint16_t 형이다.

uint16_t는 unsigned short 형을 의미.

 

다음과 같이 수정하면 warning가 사라진다

 

servAddr.sin_port = htons((unsigned short)atoi(servPORT));

 

블로그 이미지

왕왕왕왕

,

 

CChatting.zip

 

블로그 이미지

왕왕왕왕

,

 

server.c

 

client.c

 

블로그 이미지

왕왕왕왕

,