동시 통신

6834 단어
TCP 프로토콜을 사용하는 CS 아키텍처:
서버는 다중 프로세스를 사용하여 세 개의 프로세스를 만들었습니다. 부모 프로세스는 클라이언트의 연결 상황을 검사하는 데 사용되고, 하위 프로세스는 클라이언트의 메시지를 수신하는 데 사용되며, 손 프로세스는 연결된 클라이언트에게 "hello"를 보내는 데 사용됩니다.
코드 구조를 최적화하기 위해 서버의 수신 메시지와 발송 메시지는 모두 execl 함수를 사용하여 봉인됩니다.
클라이언트는 다중 스레드를 사용합니다. 메인 스레드는 서버에 메시지를 보내는 데 사용되고, 2차 스레드는 서버의 안부를 받는 데 사용됩니다.
문제가 발생했습니다: 클라이언트가 강제로 종료할 때 서버 측에서 SIGPIPE를 보내는 이상이 발생합니다.
해결 방법: 전송 함수에서 시그널 신호 함수를 사용하여 SIGPIPE 신호를 무시하고 프로세스를 종료합니다.
비고: 간단하게 학습하고 통신을 할 뿐 코드를 세밀하게 최적화하지 않고 버그가 존재한다.
서버 코드:
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
#include 

#include 
#include 

#define PORT 8888

int main()
{
    int sockfd;
    int cfd;
    int ret;
    struct sockaddr_in server_addr;
    struct sockaddr_in client_addr;
    int clen;
    char buf[1024];
    pid_t pid;

    sockfd = socket(AF_INET, SOCK_STREAM, 0);
    if (sockfd == -1)
    {
        perror("socket");
        exit(1);
    }
    printf("socket success!
"); int opt = 1; setsockopt(sockfd, SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt)); bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = inet_addr("192.168.1.16"); ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); //(struct sockaddr *)& if (ret == -1) { perror("bind"); exit(1); } printf("bind success!
"); ret = listen(sockfd, 5); if (ret == -1) { perror("listen"); exit(1); } printf("listen success!
"); clen = sizeof(client_addr); while (1) { bzero(&client_addr, sizeof(client_addr)); cfd = accept(sockfd, (struct sockaddr *)&client_addr, &clen); if (cfd == -1) { perror("accept"); exit(1); } printf("accept success!
"); printf("client port = %d,client ip = %s
",ntohs(client_addr.sin_port), inet_ntoa(client_addr.sin_addr)); // , , , pid = fork(); if (pid < 0) { perror("fork"); exit(1); } else if (pid > 0) { close(cfd); // cfd, } else { char cfd_buf[1024]; // cfd memset(cfd_buf, 0, sizeof(cfd_buf)); sprintf(cfd_buf, "%d", cfd); // cfd cfd_buf // atoi() pid_t pid2 = fork(); if (pid2 < 0) { perror("fork2"); exit(1); } else if (pid2 > 0) { execl("./recv_msg", "./recv_msg", cfd_buf, NULL); } else { execl("./send_msg", "./send_msg", cfd_buf, NULL); } } } close(sockfd); return 0; }

서버 메시지 보내기send_msg():
#include 
#include 
#include 

#include 
#include 
#include 
#include 

int main(int argc, char **argv)
{
    int ret;
    int cfd = atoi(argv[1]);  // ,
    while (1)
    {
        ret = send(cfd, "hello", strlen("hello"), 0);
        signal(SIGPIPE, SIG_IGN);
        if (ret < 0)
        {
            perror("send");
            _exit(1);
        }
        else if (ret == 0)
        {
            printf("%d is exit!
", cfd); _exit(1); } else { sleep(2); } } }

서버 수신 메시지 recv_msg():
#include 
#include 
#include 
#include 
#include 
#include 
#include 

int main(int argc, char*argv[])
{
    int ret;
    char buf[1024];
    int cfd = atoi(argv[1]);

    while (1)
    {
        memset(buf, 0, sizeof(buf));
        ret = recv(cfd, buf, sizeof(buf), 0);  //0 
        if (ret < 0)
        {
            perror("recv");
            exit(1);
        }
        else if (ret == 0)
        {
            printf("%d is exit!(child)
", cfd); shutdown(cfd, SHUT_RDWR); _exit(1); } else { printf("recv : %s
", buf); } } return 0; }

클라이언트 코드:
#include 
#include 
#include 

#include 
#include 
#include 
#include 
#include 
#include 

#define PORT 8888

void *recv_msg(void *arg)
{
    int ret;
    char buf[1024];

    int cfd = *((int *)arg);
    while (1)
    {
        memset(buf, 0, sizeof(buf));
        ret = recv(cfd, buf, sizeof(buf), 0);
        if (ret < 0)
        {
            perror("recv");
            exit(1);
        }
        else if (ret == 0)
        {
            printf("%d is exit
", cfd); pthread_exit(NULL); } else { printf("client recv: %s
", buf); } } pthread_exit(NULL); } int main() { int sockfd; int ret; char buf[1024]; pthread_t thread; struct sockaddr_in server_addr; sockfd = socket(AF_INET, SOCK_STREAM, 0); if (sockfd == -1) { perror("socket"); exit(1); } printf("socket success!
"); bzero(&server_addr, sizeof(server_addr)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(PORT); server_addr.sin_addr.s_addr = inet_addr("192.168.1.16"); ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)); if (ret == -1) { perror("connect"); exit(1); } printf("connect success!
"); if (pthread_create(&thread, NULL, recv_msg, (void *)&sockfd) != 0) { perror("pthread create"); exit(1); } while (1) { memset(buf, 0, sizeof(buf)); printf("please input send message:
"); gets(buf); send(sockfd, buf, strlen(buf), 0); } shutdown(sockfd, SHUT_RDWR); return 0; }

좋은 웹페이지 즐겨찾기