tonykang22 / study

0 stars 0 forks source link

[리눅스 개발환경] 17. TCP 소켓 통신 #88

Open tonykang22 opened 2 years ago

tonykang22 commented 2 years ago

[리눅스 개발환경] 17. TCP 소켓 통신

TCP 소켓 통신 개요

TCP 소켓 통신 함수 호출 흐름

image


TCP 소켓 통신 패킷 흐름

image



TCP 소켓 통신 함수

#include <sys/types.h>
#include <sys/socket.h>

int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
struct sockaddr {
    sa_family_t sa_family;
    char sa_data[14]; 
}


#include <sys/types.h>
#include <sys/socket.h>

int listen(int sockfd, int backlog);


#include <sys/types.h>
#include <sys/socket.h>

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


#include <sys/types.h>
#include <sys/socket.h>

int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);


#include <sys/types.h>
#include <sys/socket.h>

ssize_t send(int sockfd, const void *buf, size_t len, int flags);


#include <sys/types.h>
#include <sys/socket.h>

ssize_t recv(int sockfd, void *buf, size_t len, int flags);



예제

define handle_error(msg) \

    do { perror(msg); exit(EXIT_FAILURE); } while (0)

define LISTEN_BACKLOG 50

int main(int argc, char *argv[]) { int sfd, cfd; int portnum; struct sockaddr_in saddr; struct sockaddr_in caddr; socklen_t caddr_len; int ret; char buf[1024] = {0,};

    if (argc < 2) {
            printf("Usage : %s <port>\n", argv[0]);
            exit(1);
    }

    portnum = atoi(argv[1]);

    sfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sfd == -1)
            handle_error("socket");

memset(&saddr, 0, sizeof(struct sockaddr_in)); saddr.sin_family = AF_INET; saddr.sin_addr.s_addr = INADDR_ANY; saddr.sin_port = htons(portnum);

    if (bind(sfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1)
            handle_error("bind");

    if (listen(sfd, LISTEN_BACKLOG) == -1)
            handle_error("listen");

    caddr_len = sizeof(caddr);
    cfd = accept(sfd, (struct sockaddr *)&caddr, &caddr_len);
    if (cfd == -1)
            handle_error("accept");

    printf("accepted host(IP: %s, Port: %d)\n");
            inet_ntoa(((struct sockaddr_in *)&caddr)->sin_addr),
            ntohs(((struct sockaddr_in *)&caddr)->sin_port);

    while (1) {
            memset(buf, 0, sizeof(buf));
            ret = recv(cfd, buf, sizeof(buf), 0);
            if (ret == -1)
                    handle_error("recv");
            else if (ret == 0)
                    break;
            printf("recv data: %s\n", buf);
    }

    printf("finish.\n");
    close(cfd);
    return 0;

}


<br>

- client.c의 코드이다.
``` c
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>

#define handle_error(msg) \
        do { perror(msg); exit(EXIT_FAILURE); } while (0)

int main(int argc, char *argv[])
{
        int sockfd;
        int portnum;
        struct sockaddr_in saddr;
        socklen_t saddr_len;
        int ret;
        char buf[1024] = {0,};

        if (argc < 2) {
                printf("Usage: %s <ipaddr> <port>\n", argv[0]);
                exit(1);
        }

        portnum = atoi(argv[2]);

        sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd == -1)
                handle_error("socket");

        memset(%saddr, 0, sizeof(struct sockaddr_in));
        saddr.sin_family = AF_INET;
        saddr.sin_addr.s_addr = inet_addr(argv[1]);
        saddr.sin_port = htons(portnum);

        if (connect(sockfd, (struct sockaddr *)&saddr, sizeof(saddr)) == -1)
                handle_error("connect");

        while (1) {
                char buf[1024] = {0,};
                printf("Input message(. :quit): ");
                fgets(buf, sizeof(buf), stdin);
                if (buf[0] == '.')
                        break;
                if (send(sockfd, buf, strlen(buf), 0) == -1)
                        handle_error("send");
        }

        printf("finish.\n");
        close(sockfd);
        return 0;
}