초보 socket 프로 그래 밍 입문 상세 안내

10974 단어 socketc 언어
개발 환경
운영 플랫폼:Ubantu 14.04 LTS
질문 안내
질문 1:헤더 파일 의 질문:
4.567914 와 4.567914 는 어떤 차이 가 있 습 니까?
해답:
1.diff 로 보기:adc 는 각각 추가,삭제,수정 을 표시 합 니 다.
2.사실은 경로 가 다 르 기 때문에 서로 다른 socke.h 파일 이 있 습 니 다.   
3. 인터넷 프로 토 콜 family,즉 tcpip 프로 토 콜 의 응용 층 인터페이스   
4. 현재 잠시 알 수 없 지만 인터페이스 함수 가 아니 라 시스템 함수 로 추정 합 니 다.이 파일 은 tcpip 전송 층 에 있 을 것 으로 예상 되 는 운영 체제 에서 사용 되 어야 합 니 다.
질문 2:대소 단자 바이트 순서 문제:
1.c 언어 검 측:포인터 수치 와 주소 의 교차 응용 을 이용 하여 네트워크 이식 성 을 강화 합 니 다.
2.socket 은 바이트 순서 변환 함 수 를 제공 합 니 다:h:host;n:network;l:log 32 비트;s:short 16 비트   
3.htonl:호스트 의 32 비트 호스트 바이트 순서(ip 주소)를 네트워크 바이트 순서(열 데이터)로 변환 합 니 다.
문제 3:한 서버,한 클 라 이언 트 에 대해 다음 과 같은 대응 하 는 역할 설 이 있다.
대상 우선
대상 second
서버
클 라 이언 트
감청 자
방송 자
서 비 스 를 제공 하 다
요청 서비스
socket 프로 그래 밍 전체 과정 분석:
작성 및 삭제
서버 와 클 라 이언 트 는 같은 socket 채널 을 통 해 통신 하고 socket 채널 을 만들어 socket 연결 을 제공 합 니 다.#include <sys/socket.h>domain(도 메 인):각 도 메 인 에서 AFXXX 명령어떤 주소 형식 을 사용 할 지 결정 하고 통신 특성 을 확인 합 니 다:주소 형식 포함
type:바이트 의 종 류 를 확인 하고 자 유 롭 게 종 류 를 추가 할 수 있 습 니 다.
상용:SOCKSTREAM(즉:TCP)과 SOCKDGRAM(즉:UDP)
protocol:socket 에서 사용 하 는 전송 프로 토 콜 번 호 를 지정 합 니 다.일반적으로 0 으로 직접 설정 하면 됩 니 다.이 는 주어진 도 메 인 과 소켓 형식 으로 기본 전송 프로 토 콜 을 선택 하 는 것 을 의미 합 니 다.
반환 값:소켓 처리 코드 를 정확하게 되 돌려 줍 니 다.이 수 치 는 저장 해서 사용 할 것 이다.
서버 와 클 라 이언 트 모두 가능 합 니 다.socket 통신 IO 를 닫 습 니 다.#include <linux/socket.h>s:대표 socketfd,닫 아야 할 소켓 파일 설명자
방법
shutdown 은 socket 채널 을 비활성 상태 로 만 듭 니 다.이 채널 은 쓰기 단 을 닫 고 이 소켓 읽 기 단 을 계속 받 아 데이터 가 언제 끝 날 지 확인 한 다음 close 를 사용 하여 이 채널 을 닫 을 수 있 습 니 다.
연결 관계
IO 를 만 들 거나 소각 하거나 닫 은 후에 목표 통신 프로 세 스 를 어떻게 표시 하 는 지 알 아야 합 니 다.
원인:네트워크 에는 여러 개의 컴퓨터 가 있 고,한 컴퓨터 에 여러 개의 프로그램(프로 세 스)이 실행 되 고 있다.다음은 2 층 관계 입 니 다.
1)대상 컴퓨터 의 네트워크 주소
2)대상 컴퓨터 의 대상 프로 세 스 가 대표 하 는 포트 번호
그래서 지금 당신 이 알 아야 할 것 은 다음 과 같은 몇 가지 가 있 습 니 다.
 1.바이트 순서:위의 문제 2 를 직접 보면 되 고 관 계 를 간단하게 전환 할 수 있다.
 2.주소 형식:서로 다른 인터넷 주소 에 따라에서 서로 다른 구조 체 를 정의 하고 일부 socket 함수 매개 변 수 를 호출 합 니 다.아래 와 같다   
 3.주소 구조 체 를 정의 하고 실제 불 러 오 는 수치 에 따라 socket API 실 참 으로 합 니 다.   
 4.주소 진 변환:주 소 를 바 이 너 리 와 텍스트 문자열 형식 으로 변환 합 니 다.inet_ntop 또는 inetpton
바 인 딩 이 어 서버 에 서 는 바 인 딩(관련)주소 와 소켓 이 필요 합 니 다.주어진 sockfd 에 sockaddr 구조 데 이 터 를 연결 합 니 다.서버 에서 소켓 을(도 메 인)주소 에 연결 해 야 클 라 이언 트 가 연결(connect)에 성공 할 수 있 습 니 다.int socket(int domain,int type,int protocol);
sockfd:소켓 파일 설명자,socket 에서 돌아 오 는 값 입 니 다.
my_addr:(서버)네트워크 주소 정보
반환 값:정확 한 바 인 딩 주소 와 소켓 여 부 를 판단 합 니 다.
연결 하기 전에 소켓(socket)을 만 들 고 연결 기반(bid)을 만 들 었 습 니 다.그렇다면 통신 에 앞서 socket 채널 을 연결 하기 위 한 것 이다.int shutdown(int s,int how); sockfd:소켓 파일 설명자,socket 에서 돌아 오 는 값 입 니 다.
serv_addr:네트워크 주소 정보
반환 값:정확 한 연결 여 부 를 판단 하려 면 클 라 이언 트 프로그램 이 connect 가 되 돌아 오 는 오 류 를 처리 해 야 합 니 다.
지금까지 connect 함수 의 매개 변수 유형 과 개 수 는 모두 bid 와 같다 는 것 을 발 견 했 을 지도 모른다.
TCPIP 프로 토 콜 에 따라 연결 해 야 할 정보:IP 주소,포트 번호 만으로 도 충분 합 니 다.나머지 MAC 주소 등 은 socket 안에 있 으 니 신경 쓸 필요 가 없습니다.
감청 에 주의해 야 할 것 은 이런 연결 은 서버 에서 어떤 클 라 이언 트 가 연결 을 요청 하 는 지 확인 해 야 한 다 는 것 이다.따라서 서버 는 먼저 실행 요청 클 라 이언 트(임의의)연결 상태 에 들 어가 listen(감청)상태 에 들 어 갑 니 다.사용 함수:int bind(int sockfd,struct sockaddr * my_addr,int addrlen);
s:서버 소켓 설명자,socket 에서 돌아 오 는 값 입 니 다.
backlog:동시에 처리 할 수 있 는 최대 연결 요 구 를 지정 합 니 다.
함수 반환 값:감청 상태 에 올 바 르 게 들 어 갔 는 지 여부
연결 할 때 서버 는 이미 listen 상태 에 들 어 갔 고 이어서 호출 되 었 습 니 다.int connect (int sockfd,struct sockaddr * serv_addr,int addrlen);
s:서버 소켓 설명자,socket 에서 돌아 오 는 값 입 니 다.
addr:연 결 된 클 라 이언 트 의 소켓 데이터
addrlen:연 결 된 클 라 이언 트 의 소켓 데이터 길이
복귀:연 결 된 클 라 이언 트 의 파일 설명자
데이터 읽 기 및 전송
지금까지 서버 와 클 라 이언 트 는 양 방향 통신 의 기초 준 비 를 마 쳤 다.
send 와 recv 는 잠시 언급 하지 않 고 독자 스스로 API 를 찾 습 니 다.

int recv(int s,void *buf,int len,unsigned int flags); 
int send(int s,const void * msg,int len,unsigned int falgs);
다음은 코드 와 직접 연 결 됩 니 다.

//        and socket     
#include <stdio.h> //
#include <stdlib.h> //
#include <errno.h> //errno      
#include <unistd.h> //
#include <stddef.h> //

#include <sys/socket.h> //  socket API
#include <sys/un.h> // 
#include <sys/types.h> //socket API         
#include <arpa/inet.h> //      
#include <netinet/in.h> //     ( )、       
클 라 이언 트 코드:

#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>

#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 8000

int main(int argc, char *argv[])
{
 struct sockaddr_in servaddr;
 char buf[MAXLINE];
 int sockfd, n;
 sockfd = Socket(AF_INET, SOCK_STREAM, 0);
 bzero(&servaddr, sizeof(servaddr));
 servaddr.sin_family = AF_INET;
 inet_pton(AF_INET, "192.168.191.6", &servaddr.sin_addr);
 servaddr.sin_port = htons(SERV_PORT);
 Connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
 while (fgets(buf, MAXLINE, stdin) != NULL) {
 Write(sockfd, buf, strlen(buf));
 n = Read(sockfd, buf, MAXLINE);
 if (n == 0)
 printf("the other side has been closed.
"); else Write(STDOUT_FILENO, buf, n); } Close(sockfd); return 0; }
서버 코드:

#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include "wrap.h"

#define MAXLINE 80
#define SERV_PORT 8000

int main(void)
{
 struct sockaddr_in servaddr, cliaddr;
 socklen_t cliaddr_len;
 int listenfd, connfd;
 char buf[MAXLINE];
 char str[INET_ADDRSTRLEN];
 int i, n;

 listenfd = Socket(AF_INET, SOCK_STREAM, 0);

 bzero(&servaddr, sizeof(servaddr));
 servaddr.sin_family = AF_INET;
 servaddr.sin_addr.s_addr = inet_addr("192.168.191.6");
 servaddr.sin_port = htons(SERV_PORT);

 Bind(listenfd, (struct sockaddr *) &servaddr, sizeof(servaddr));
 Listen(listenfd, 20);
 printf("Accepting connections ...
"); while (1) { cliaddr_len = sizeof(cliaddr); connfd = Accept(listenfd, (struct sockaddr *) &cliaddr, &cliaddr_len); while (1) { n = Read(connfd, buf, MAXLINE); if (n == 0) { printf("the other side has been closed.
"); break; } printf("received from %s at PORT %d
", (char *)inet_ntop(AF_INET, &cliaddr.sin_addr, str, sizeof(str)), (int)ntohs(cliaddr.sin_port)); for (i = 0; i < n; i++) buf[i] = toupper(buf[i]); Write(connfd, buf, n); } Close(connfd); } }
실행 결과:

hhc@my:~/sharefile/socket/tcp$ ./server &
[1] 15371
hhc@my:~/sharefile/socket/tcp$ Accepting connections ...
hhc@my:~/sharefile/socket/tcp$ ./client
this is a test! 
received from 192.168.191.6 at PORT 53685
THIS IS A TEST!
개인 패키지 socket 인터페이스 함수:

#include "wrap.h"

void perr_exit(const char *s)
{
 perror(s);
 exit(1);
}

int Accept(int fd, struct sockaddr *sa, socklen_t * salenptr)
{
 int n;
 again:
 if ((n = accept(fd, sa, salenptr)) < 0) {
 if ((errno == ECONNABORTED) || (errno == EINTR))
 goto again;
 else
 perr_exit("accept error");
 }
 return n;
}

void Bind(int fd, const struct sockaddr *sa, socklen_t salen)
{
 if (bind(fd, sa, salen) < 0)
 perr_exit("bind error");
}

void Connect(int fd, const struct sockaddr *sa, socklen_t salen)
{
 if (connect(fd, sa, salen) < 0)
 perr_exit("connect error");
}

void Listen(int fd, int backlog)
{
 if (listen(fd, backlog) < 0)
 perr_exit("listen error");
}

int Socket(int family, int type, int protocol)
{
 int n;
 if ((n = socket(family, type, protocol)) < 0)
 perr_exit("socket error");
 return n;
}

ssize_t Read(int fd, void *ptr, size_t nbytes)
{
 ssize_t n;
 again:
 if ((n = read(fd, ptr, nbytes)) == -1) {
 if (errno == EINTR)
 goto again;
 else
 return -1;
 }
 return n;
}

ssize_t Write(int fd, const void *ptr, size_t nbytes)
{
 ssize_t n;
 again:
 if ((n = write(fd, ptr, nbytes)) == -1) {
 if (errno == EINTR)
 goto again;
 else
 return -1;
 }
 return n;
}

void Close(int fd)
{
 if (close(fd) == -1)
 perr_exit("close error");
}

ssize_t Readn(int fd, void *vptr, size_t n)
{
 size_t nleft;
 ssize_t nread;
 char *ptr;
 ptr = vptr;
 nleft = n;
 while (nleft > 0) {
 if ((nread = read(fd, ptr, nleft)) < 0) {
 if (errno == EINTR)
 nread = 0;
 else
 return -1;
 } else if (nread == 0)
 break;
 nleft -= nread;
 ptr += nread;
 }
 return n - nleft;
}

ssize_t Writen(int fd, const void *vptr, size_t n)
{
 size_t nleft;
 ssize_t nwritten;
 const char *ptr;
 ptr = vptr;
 nleft = n;
 while (nleft > 0) {
 if ((nwritten = write(fd, ptr, nleft)) <= 0) {
 if (nwritten < 0 && errno == EINTR)
 nwritten = 0;
 else
 return -1;
 }
 nleft -= nwritten;
 ptr += nwritten;
 }
 return n;
}

ssize_t my_read(int fd, char *ptr)
{
 static int read_cnt;
 static char *read_ptr;
 static char read_buf[100];
 if (read_cnt <= 0) {
 again:
 if ((read_cnt = read(fd, read_buf, sizeof(read_buf))) < 0) {
 if (errno == EINTR)
 goto again;
 return -1;
 } else if (read_cnt == 0)
 return 0;
 read_ptr = read_buf;
 }
 read_cnt--;
 *ptr = *read_ptr++;
 return 1;
}

ssize_t Readline(int fd, void *vptr, size_t maxlen)
{
 ssize_t n, rc;
 char c, *ptr;
 ptr = vptr;
 for (n = (ssize_t)1; n < (ssize_t)maxlen; n++) {
 if ((rc = my_read(fd, &c)) == 1) {
 *ptr++ = c;
 if (c == '
') break; } else if (rc == 0) { *ptr = 0; return n - 1; } else return -1; } *ptr = 0; return n; }
이상 이 바로 본 고의 모든 내용 입 니 다.여러분 의 학습 에 도움 이 되 고 저 희 를 많이 응원 해 주 셨 으 면 좋 겠 습 니 다.

좋은 웹페이지 즐겨찾기