zoukankan      html  css  js  c++  java
  • 【linux高级程序设计】(第十三章)Linux Socket网络编程基础 3

    使用之前的函数实现的简单聊天程序

    TCP协议

    双方实时发送/接收消息

    实现后的问题:

      可能是我虚拟机的IP地址配得有问题吧。在一台电脑上面开两个终端,用127.0.0.1的IP收发可以互通。但是两个虚拟机就不行了,用192.168的IP段,能够ping通但是代码接收不到消息。

      还有,两个进程都是接收到消息后,需要我自己按一下回车才能发送消息。

    服务器端代码:

    #include<stdio.h>
    #include<string.h>
    #include<errno.h>
    #include<sys/socket.h>
    #include<resolv.h>
    #include<stdlib.h>
    #include<netinet/in.h>
    #include<arpa/inet.h>
    #include<unistd.h>
    #define MAXBUF 1024
    int main(int argc, char *argv[])
    {
        int pid;
        int sockfd, new_fd;
        socklen_t len;
        struct sockaddr_in my_addr, their_addr;
        unsigned int myport, lisnum;
        char buf[MAXBUF + 1];
        if(argv[2])
            myport = atoi(argv[2]);  //命令行字符串转为整数,端口
        else 
            myport = 7575;           //默认端口
        
        if(argv[3])
            lisnum = atoi(argv[3]);  //监听队列的大小
        else
            lisnum = 5;
        
        //创建socket对象, IPv4, TCP, 默认协议
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)   //创建socket对象
        {
            perror("socket");
            exit(EXIT_FAILURE);
        }
        
        bzero(&my_addr, sizeof(my_addr));
        my_addr.sin_family = AF_INET;               //地址协议
        my_addr.sin_port = htons(myport);           //地址端口
        if(argv[1])
            my_addr.sin_addr.s_addr = inet_addr(argv[1]);   //指定IP地址 从点分十进制字符串转为32位二进制
        else
            my_addr.sin_addr.s_addr = INADDR_ANY;   //否则设置为本机任意地址
        
        char mybuf[128];
        inet_ntop(AF_INET, &my_addr.sin_addr.s_addr, mybuf, 128);
        printf("the ip is '%s'
    ", mybuf);
        //绑定地址信息
        if(bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1)
        {
            perror("bind");
            exit(EXIT_FAILURE);
        }
        
        //监听网络
        if(listen(sockfd, lisnum) == -1)
        {
            perror("listen");
            exit(EXIT_FAILURE);
        }
        printf("wait for connect
    ");
        len = sizeof(struct sockaddr);
        
        //阻塞等待连接
        if((new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &len)) == -1)
        {
            perror("accept");
            exit(EXIT_FAILURE);
        }
        else   //打印接收到的信息
        {        
            printf("server: got connection from %s, port %d, socket %d
    ", inet_ntoa(their_addr.sin_addr), ntohs(their_addr.sin_port), new_fd);
        }
        
        //创建新进程
        if(-1 == (pid = fork()))
        {
            perror("fork");
            exit(EXIT_FAILURE);
        }
        else if(0 == pid)   //子进程用于发送消息
        {
            while(1)
            {
                bzero(buf, MAXBUF + 1);
                printf("input the message to send:");
                fgets(buf, MAXBUF, stdin);
                if(!strncasecmp(buf, "quit", 4))
                {
                    printf("i will close the connect!
    ");
                    break;
                }
                len = send(new_fd, buf, strlen(buf) - 1, 0);
                if(len < 0)
                {
                    printf("message '%s' send failure! errno code is %d, errno message is '%s'
    ", buf, errno, strerror(errno));
                    break;
                }
            }
        }
        else  //父进程用于接收消息 
        {
            while(1)
            {
                bzero(buf, MAXBUF + 1);
                len = recv(new_fd, buf, MAXBUF, 0);
                if(len > 0)
                {
                    printf("message recv successful : '%s', %dByte recv
    ", buf, len);
                }
                else if(len < 0)
                {
                    printf("recv failure! errno code is %d, errno message is '%s'
    ", errno, strerror(errno));
                    break;
                }
                else
                {
                    printf("the other one close quit
    ");
                    break;
                }
            }
        }
        
        close(new_fd);
        close(sockfd);
        return 0;
    }

    客户端代码:

    #include<stdio.h>
    #include<string.h>
    #include<errno.h>
    #include<sys/socket.h>
    #include<resolv.h>
    #include<stdlib.h>
    #include<netinet/in.h>
    #include<arpa/inet.h>
    #include<unistd.h>
    #define MAXBUF 1024
    int main(int argc, char **argv)
    {
        int sockfd, len;
        struct sockaddr_in dest;
        char buffer[MAXBUF + 1];
        if(argc != 3)
        {
            printf(" error format, it must be :
     		%s IP port
    ", argv[0]);
            exit(EXIT_FAILURE);
        }
        
        //创建socket对象
        if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
        {
            perror("Socket");
            exit(errno);
        }
        printf("socket created
    ");
        bzero(&dest, sizeof(dest));
        dest.sin_family = AF_INET;             //地址协议
        dest.sin_port = htons(atoi(argv[2]));  //对方端口
        //对方IP地址
        if(inet_aton(argv[1], (struct in_addr *)&dest.sin_addr.s_addr) == 0)  
        {
            perror("argv[1]");
            exit(errno);
        }
        //发起连接
        if(connect(sockfd, (struct sockaddr *)&dest, sizeof(dest)) == -1)
        {
            perror("Connect");
            exit(errno);
        }
        printf("server connected
    ");
        pid_t pid;
        
        //创建子进程
        if(-1 == (pid = fork()))
        {
            perror("fork");
            exit(errno);
        }
        else if(pid == 0)       //子进程用于数据接收
        {
            while(1)
            {
                bzero(buffer, MAXBUF + 1);
                len = recv(sockfd, buffer, MAXBUF, 0);
                if(len > 0)
                {
                    printf("recv successful:'%s', %d byte recv
    ", buffer, len);
                }
                else if(len < 0)
                {
                    perror("recv");
                    break;
                }
                else
                {
                    printf("the other one close, quit
    ");
                    break;
                }
            }
        }
        else   //父进程用于数据发送
        {
            while(1)
            {
                bzero(buffer, MAXBUF + 1);
                printf("input the message to send:");
                fgets(buffer, MAXBUF, stdin);
                if(!strncasecmp(buffer, "quit", 4))
                {
                    printf("i will close the connect!
    ");
                    break;
                }
                len = send(sockfd, buffer, strlen(buffer) - 1, 0);
                if(len < 0)
                {
                    printf("message '%s' send failure! errno code is %d, errno message is '%s'
    ", buffer, errno, strerror(errno));
                    break;
                }
            }
        }
        close(sockfd);
        return 0;
    }
  • 相关阅读:
    telnet和ssh
    sersync实现实时同步
    rsync服务端一键安装rsync脚本(源码)
    rsync客户端一键安装rsync脚本(源码)
    rsync客户端一键安装rsync脚本(非源码)
    centos 建立Clamav自动扫描脚本
    DELL T110II Server如何通过RAID 级别迁移的方式在OMSA下实现磁盘阵列扩容?
    Dell PowerEdgeServerT110II USB Boot更新
    Centos7最小安装下Install Clamav(2017-06-09最后更新)
    Centos7 samba 匿名共享 简单config
  • 原文地址:https://www.cnblogs.com/dplearning/p/4700125.html
Copyright © 2011-2022 走看看