zoukankan      html  css  js  c++  java
  • 自测之Lesson15:TCP&UDP网络编程

    题目:编写一个TCP通信的程序。

    实现代码:

    #include <stdio.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <string.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #define PORT 0xaaaa
    
    // 服务端
    void startServe()
    {
            int iRet;
    
            // socket()
            int fd;                                         // 文件描述符
            fd = socket(PF_INET, SOCK_STREAM, 0);           // 创建文件描述符,并确定是用TCP还是UDP等
            if (fd < 0) {
                    perror("fail socket");
                    return;
            }
        
            // bind()
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(PORT);
            addr.sin_addr.s_addr = htonl(INADDR_ANY);       // 即使目标地址不是我,只要发到该计算机上,我就能接收
    
            iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr)); // 将文件描述符与本机地址绑定
            if (iRet < 0) {
                    perror("fail bind");
                    close(fd);                              // 释放资源
                    return;
            }    
        
            // listen()
            iRet = listen(fd, 5);                   // 最多监听5个连接请求
            if (iRet < 0) {
                    perror("fail listen");
                    close(fd);
                    return;
            }
            printf("Server start OK, wait connect...
    ");
    
            // accept()
            char szBuf[1024];
            char szMsg[] = "Welcome...";
            struct sockaddr_in clientAddr;                  // 客户端地址
            socklen_t addrlen = sizeof(clientAddr);
            while(1) {
                    int newFd;                              // 此newFd用于与客户端通信
                    newFd = accept(fd, (struct sockaddr*)&clientAddr, &addrlen);
                    if (newFd < 0) {
                            perror("fail accept");
                            break;
                    }
    
                    char *pClientAddr = inet_ntoa(clientAddr.sin_addr);     // 整数IP转字符串IP
                    int clientPort = ntohs(clientAddr.sin_port);            // 网络字节序转主机字节序
                    printf("Connect from %s:%d
    ", pClientAddr, clientPort);
                    memset(szBuf, 0, 1024);
                    iRet = read(newFd, szBuf, 1024);
                    if (iRet < 0) {
                            perror("fail read");
                            break;
                    }
                    printf("Recv:%s
    ", szBuf);
                    write(newFd, szMsg, strlen(szMsg));
                    close(newFd);           // 关闭当前accept创建的文件描述符
            }
            close(fd);
            return;
    }
    
    // 客户端
    void startClient()
    {
            int iRet;
    
            // socket()
            int fd;
            fd = socket(PF_INET, SOCK_STREAM, 0);
            if(fd < 0) {
                    perror("fail socket");
                    return;
            }
    
            // connect()
            struct sockaddr_in srvAddr;
            srvAddr.sin_family = AF_INET;
            srvAddr.sin_addr.s_addr = inet_addr("192.168.85.128");          // 服务端的ip地址
            srvAddr.sin_port = htons(PORT);                                 // 服务端的端口号
            iRet = connect(fd, (struct sockaddr*)&srvAddr, sizeof(srvAddr));
            if (iRet != 0) {
                    perror("fail connect");
                    return;
            }
            printf("Connect success
    ");
            fprintf(stderr, "Send:");
    
            // read() & write()
            char szBuf[1024];
            memset(szBuf, 0, 1024);
            read(STDIN_FILENO, szBuf, 1024);                // 从标准输入 输入消息
            write(fd, szBuf, strlen(szBuf));
            char szRcv[1024];
    
            memset(szRcv, 0, 1024);
            read(fd, szRcv, 1024);
            printf("[CLIENT]Rcv:%s
    ", szRcv);
    
            close(fd);
            return;
    }
    
    int main(int argc, char **argv)
    {
            if (argc != 2 ||
                (strcmp(argv[1], "s") && strcmp(argv[1], "c"))) {
                    printf("Usage: %s [ s | c ]
    ", argv[0]);
                    printf("	s: start server
    ");
                    printf("	c: start client
    ");
                    return 0;
            }
            if (argv[1][0] == 's') {
                    startServe();
            }
            else if (argv[1][0] == 'c') {
                    startClient();
            }
            return 0;
    }
    
    /* ReadMe */
    /*
     * 先启动服务端 --> ./a.out s
     * 再启动客户端 --> ./a.out c
     */
    

    题目:编写一个UDP通信的程序。

      

    实现代码:

    #include <stdio.h>
    #include <unistd.h>
    #include <string.h>
    #include <arpa/inet.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    
    #define SRV_PORT 0xaaaa                 // 服务端 端口号
    #define CLI_PORT 0xbbbb                 // 客户端 端口号
    #define IP_ADDRESS "10.162.73.120"
    
    void startServer()
    {
            int iRet;
        
            // socket()
            int fd; 
            fd = socket(PF_INET, SOCK_DGRAM, 0); 
            if (fd < 0) {
                    perror("fail socket");
                    return;
            }
        
            // bind()
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_addr.s_addr = htonl(INADDR_ANY);
            addr.sin_port = htons(SRV_PORT);
            iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
            if (iRet != 0) {
                    perror("fail bind");
                    return;
            }
    
            // recvfrom() & sendto()
            struct sockaddr_in cliAddr;
            socklen_t addrLen = sizeof(cliAddr);
            char szRcv[1024];
            char szSnd[1024];
            while(1) {
                    // recvfrom()
                    memset(szRcv, 0, 1024);
                    iRet = recvfrom(fd, szRcv, 1024, 0, (struct sockaddr*)&cliAddr, &addrLen);
                    if (iRet < 0) {
                            perror("fail recvfrom");
                            close(fd);
                            break;
                    }
                    char *pcliAddr = inet_ntoa(cliAddr.sin_addr);
                    int cliPort = ntohs(cliAddr.sin_port);
                    printf("Recv from client[%s:%d]
    ", pcliAddr, cliPort);
                    printf("Recv:%s
    ", szRcv);
    
                    // sendto()
                    fprintf(stderr, "Send:");
                    memset(szSnd, 0, 1024);
                    read(STDIN_FILENO, szSnd, 1024);
                    iRet = sendto(fd, szSnd, strlen(szSnd), 0, (struct sockaddr*)&cliAddr, addrLen);
    
            }
            close(fd);
    }
    
    void startClient()
    {
            int iRet;
    
            // socket()
            int fd;
            fd = socket(PF_INET, SOCK_DGRAM, 0);
            if (fd < 0) {
                    perror("fail socket");
                    return;
            }
    
            // bind()
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_addr.s_addr = htonl(INADDR_ANY);
            addr.sin_port = htons(CLI_PORT);
            iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
            if (iRet != 0) {
                    perror("fail bind");
                    return;
            }
    
            // recvfrom() & sendto()
            struct sockaddr_in srvAddr;
            socklen_t addrLen = sizeof(srvAddr);
            // 对端的地址信息,用于sendto()函数
            srvAddr.sin_family = AF_INET;
            srvAddr.sin_addr.s_addr = inet_addr(IP_ADDRESS);
            srvAddr.sin_port = htons(SRV_PORT);
            char szRcv[1024];
            char szSnd[1024];
            while(1) {
                    // sendto()
                    fprintf(stderr, "Send:");
                    memset(szSnd, 0, 1024);
                    read(STDIN_FILENO, szSnd, 1024);
                    sendto(fd, szSnd, strlen(szSnd), 0, (struct sockaddr*)&srvAddr, addrLen);
    
                    // read()
                    memset(szRcv, 0, 1024);
                    read(fd, szRcv, 1024);          // 上面的sendto()已经获得对端地址,此处可简写
                    printf("Recv:%s
    ", szRcv);
            }
            close(fd);
    }
    
    int main(int argc, char **argv)
    {
            if (argc != 2 ||
                    (strcmp(argv[1], "c") && strcmp(argv[1], "s")))
            {
                    printf("Usage:%s [ s | c ]
    ", argv[0]);
                    printf("	s: start to server
    ");
                    printf("	c: start to client
    ");
                    return 0;
            }
            if (argv[1][0] == 's') {
                    startServer();
            }
            else if (argv[1][0] == 'c') {
                    startClient();
            }
            return 0;
    }
    

      

    题目:编写一个抓包程序,要求抓取封装TCP报文段的包,并打印出包的头部信息。

    实现代码:

    #include <stdio.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <sys/types.h>
    #include <string.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    #define PORT 0Xaaaa                     // 此端口仅用于bind(),而该程序可抓发送到任意端口的包
    
    typedef struct _ipHeader {
    //      unsigned char ucVer:4;
    //      unsigned char ucHeadLen:4;
            unsigned char ucVerHeadLen;             // 不应该在此处用位域,可在后面提取位数
            unsigned char ucTos;
            unsigned short usLen;
            unsigned short usIdent;
    //      unsigned short usFlag:3;
    //      unsigned short usOffset:13;
            unsigned short usFlagOffset;
            unsigned char ucTTL;
            unsigned char ucProtocol;
            unsigned short usChkSum;
    //      unsigned int uiSrcIp;
    //      unsigned int uiDestIp;
            struct in_addr SrcIp;
            struct in_addr DestIp;
            char data[0];
    } IP_HEADER;
    
    
    typedef struct _tcpHeader {
            unsigned short SrcPort;
            unsigned short DestPort;
            unsigned int Seq;
            unsigned int Ack;
    //      unsigned short HeadLen:4;
    //      unsigned short Save:6;
    //      unsigned short URG:1;
    //      unsigned short ACK:1;
    //      unsigned short PSH:1;
    //      unsigned short RST:1;
    //      unsigned short SYN:1;
    //      unsigned short FIN:1;
            unsigned short HeadLenFlag;             // 包括首部长度、保留、URG标志等字段
            unsigned short Window;
            unsigned short ChkSum;
            unsigned short UrgPoint;
            char data[0];
    } TCP_HEADER;
    
    
    void printIpHeader(char szBuf[])
    {
            IP_HEADER *pHeader = (IP_HEADER*)szBuf;
            printf("
    ================IP HEADER================
    ");
            printf("	Version:%d
    ", (pHeader->ucVerHeadLen) >> 4);
            printf("	HeadLen:%d
    ", (pHeader->ucVerHeadLen) & 0x0f);
            printf("	SOUR IP:%s
    ", inet_ntoa(pHeader->SrcIp));
            printf("	DEST IP:%s
    ", inet_ntoa(pHeader->DestIp));
            printf("=========================================
    ");
    }
    
    void printTcpHeader(char szBuf[])
    {
            TCP_HEADER *pHeader = (TCP_HEADER*)szBuf;
            printf("
    ===============TCP HEADER================
    ");
            printf("	SOUR PORT:%d
    ", ntohs(pHeader->SrcPort));
            printf("	DEST PORT:%d
    ", ntohs(pHeader->DestPort));
            printf("=========================================
    ");
    }
    
    void startCapturePacket()
    {
            int iRet;
    
            int fd;
            fd = socket(PF_INET, SOCK_RAW, IPPROTO_TCP/* = NUM'6' */);      // 抓取封装TCP报文段的IP数据报
            if (fd < 0) {
                    perror("fail socket");
                    return;
            }
    
            struct sockaddr_in addr;
            addr.sin_family = AF_INET;
            addr.sin_port = htons(PORT);
            addr.sin_addr.s_addr = htonl(INADDR_ANY);
    
            iRet = bind(fd, (struct sockaddr*)&addr, sizeof(addr));
            if (iRet < 0) {
                    perror("fail bind");
                    close(fd);
                    return;
            }
    
            char szBuf[1024];
            while(1) {
                    memset(szBuf, 0, 1024);
                    read(fd, szBuf, 1024);                  // 将抓到的包整个存到szBuf中,此处szBuf的大小不是很合适
                    printIpHeader(szBuf);                   // 打印IP头部部分信息
                    printTcpHeader(szBuf);                  // 打印TCP报文端头部部分信息
            }
            close(fd);
            return;
    }
    
    
    
    int main()
    {
            startCapturePacket();
            return 0;
    }
    

      

     

  • 相关阅读:
    Ubiquitous Religions-并查集(5)
    The Suspects-并查集(4)
    Is It A Tree?-并查集(3)
    Html5 缓存
    HTML 5 Web 存储 localStorage
    html5画布显示图片问题
    html5画布
    html5拖动
    html5音频及视频
    linux mint的小方法
  • 原文地址:https://www.cnblogs.com/xzxl/p/8560885.html
Copyright © 2011-2022 走看看