zoukankan      html  css  js  c++  java
  • Linux 网络编程详解三(p2p点对点聊天)

    //p2p点对点聊天多进程版--服务器(信号的使用)
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <signal.h>
    #include <sys/wait.h>
    
    void handler(int sign)
    {
        if(sign==SIGUSR1)
            printf("recv signal!
    ");
        exit(0);
    }
    
    int main(int arg, char *args[])
    {
        //create socket
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd == -1)
        {
            perror("socket() err");
            return -1;
        }
        //reuse server socket
        int optval = 1;
        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &optval, sizeof(optval))
                == -1)
        {
            perror("setsockopt() err");
            return -1;
        }
        //bind port and ip
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(8080);
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        if (bind(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
        {
            perror("bind() err");
            return -1;
        }
        //listen 维护两个队列
        if (listen(sockfd, SOMAXCONN) == -1)
        {
            perror("listen() err");
            return -1;
        }
        //accept
        struct sockaddr_in peeraddr;
        socklen_t peerlen = sizeof(peeraddr);
        int conn = accept(sockfd, (struct sockaddr *) &peeraddr, &peerlen);
        if (conn == -1)
        {
            perror("accept() err");
            return -1;
        }
        printf("accept by %s
    ", inet_ntoa(peeraddr.sin_addr));
        pid_t pid = 0;
        pid = fork();
        if (pid == -1)
        {
            perror("fork() err");
            return -1;
        }
        //父进程接收客户端信息,打屏
        if (pid > 0)
        {
            char recvbuf[1024] = { 0 };
            int rc = 0;
            while (1)
            {
                rc = read(conn, recvbuf, 1024);
                if (rc < 0)
                {
                    perror("read() err");
                    break;
                } else if (rc == 0)
                {
                    printf("client is closed !
    ");
                    break;
                }
                //printf("%s
    ");
                write(STDOUT_FILENO, recvbuf, rc);
                memset(recvbuf, 0, 1024);
            }
            //发送信号,关闭子进程
            kill(pid,SIGUSR1);
            //关闭客户端连接套接字
            close(conn);
            close(sockfd);
            //等待子进程
            int ret=0;
            while(1)
            {
                ret=wait(NULL);
                printf("子进程pid=%d
    ",ret);
                if(ret==-1)
                {
                    if(errno==EINTR)
                        continue;
                    break;
                }
            }
        }
        //子进程读取用户输入,发送给客户端
        if (pid == 0)
        {
            //安装信号
            struct sigaction act;
            act.sa_handler=handler;
            sigemptyset(&act.sa_mask);
            act.sa_flags=0;
            if(sigaction(SIGUSR1,&act,NULL)==-1)
            {
                printf("sigaction() failed! 
    ");
                exit(0);
            }
            //关闭服务器监听套接字
            close(sockfd);
            char sendbuf[1024] = { 0 };
            while (1)
            {
                if (read(STDIN_FILENO, sendbuf, 1024) == -1)
                {
                    perror("read() err");
                    //关闭客户端连接套接字
                    close(conn);
                    exit(0);
                }
                write(conn, sendbuf, strlen(sendbuf));
                memset(sendbuf, 0, 1024);
            }
        }
        return 0;
    }
    //p2p点对点聊天多进程版--客户端
    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <unistd.h>
    #include <errno.h>
    #include <sys/types.h>          /* See NOTES */
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    int main(int arg, char *args[])
    {
        int sockfd = socket(AF_INET, SOCK_STREAM, 0);
        if (sockfd == -1)
        {
            perror("socket() err");
            return -1;
        }
        //connect
        struct sockaddr_in addr;
        addr.sin_family = AF_INET;
        addr.sin_port = htons(8080);
        addr.sin_addr.s_addr = inet_addr("127.0.0.1");
        if (connect(sockfd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
        {
            perror("connect() err");
            return -1;
        }
        pid_t pid = 0;
        pid = fork();
        if (pid == -1)
        {
            perror("fork() err");
            return -1;
        }
        int rc = 0;
        char buf[1024] = { 0 };
        //子进程接收信息
        if (pid == 0)
        {
            while (1)
            {
                rc = read(sockfd, buf, 1024);
                if (rc < 0)
                {
                    perror("read err");
                    close(sockfd);
                    exit(0);
                } else if (rc == 0)
                {
                    printf("server closed!
    ");
                    close(sockfd);
                    exit(0);
                }
                write(STDOUT_FILENO, buf, rc);
                memset(buf, 0, 1024);
            }
        }
        //父进程发送数据
        if (pid > 0)
        {
            while (1)
            {
                if (read(STDIN_FILENO, buf, 1024) == -1)
                {
                    perror("read() err");
                    close(sockfd);
                    exit(0);
                }
                write(sockfd, buf, strlen(buf));
                memset(buf, 0, 1024);
            }
        }
        return 0;
    }
    .SUFFIXES:.c .o
    CC=gcc
    SRCS1=tec01.c
    SRCS2=hello.c
    OBJS1=$(SRCS1:.c=.o)
    OBJS2=$(SRCS2:.c=.o)
    EXEC1=runc
    EXEC2=hello
    
    start:$(OBJS1) $(OBJS2)
        $(CC) -o $(EXEC1) $(OBJS1)
        $(CC) -o $(EXEC2) $(OBJS2)
        @echo "--------OK--------"
    .c.o:
        $(CC) -Wall -g -o $@ -c $<
    clean:
        rm -f $(OBJS1)
        rm -f $(EXEC1)
        rm -f $(OBJS2)
        rm -f $(EXEC2)
  • 相关阅读:
    Java语法总结 线程
    Java多线程编程总结
    eclipse插件开发
    Java私塾的一些基础练习题(一)
    反射练习
    内部类实现动态链表(增,删,查,打印)
    oracle 存储过程第四天
    java 面向对象个人理解
    jsp的flash小例子
    oralcle 存储过程批处理
  • 原文地址:https://www.cnblogs.com/zhanggaofeng/p/6131783.html
Copyright © 2011-2022 走看看