zoukankan      html  css  js  c++  java
  • linux:C++的socket编程

      基本的局域网聊天

      局域网聊天TCP服务端:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    #include <thread>
    #include <iostream>
    #define PORT 7000
    #define QUEUE 20
    int conn;
    void thread_task() {
    }
    
    int main() {
        //printf("%d
    ",AF_INET);
        //printf("%d
    ",SOCK_STREAM);
        int ss = socket(AF_INET, SOCK_STREAM, 0);
        //printf("%d
    ",ss);
        struct sockaddr_in server_sockaddr;
        server_sockaddr.sin_family = AF_INET;
        server_sockaddr.sin_port = htons(PORT);
        //printf("%d
    ",INADDR_ANY);
        server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        if(bind(ss, (struct sockaddr* ) &server_sockaddr, sizeof(server_sockaddr))==-1) {
            perror("bind");
            exit(1);
        }
        if(listen(ss, QUEUE) == -1) {
            perror("listen");
            exit(1);
        }
    
        struct sockaddr_in client_addr;
        socklen_t length = sizeof(client_addr);
        ///成功返回非负描述字,出错返回-1
        conn = accept(ss, (struct sockaddr*)&client_addr, &length);
        if( conn < 0 ) {
            perror("connect");
            exit(1);
        }
    
        char buffer[1024];
        //创建另外一个线程
        //std::thread t(thread_task);
        //t.join();
        //char buf[1024];
        //主线程
        while(1) {
    
            // memset(buf, 0 ,sizeof(buf));
            // if(fgets(buf, sizeof(buf),stdin) != NULL) {
            //     send(conn, buf, sizeof(buf), 0);    
            // }
    
            memset(buffer, 0 ,sizeof(buffer));
            int len = recv(conn, buffer, sizeof(buffer), 0);
            if(strcmp(buffer, "exit
    ") == 0) break;
            printf("%s", buffer);
            //必须要有返回数据, 这样才算一个完整的请求
            send(conn, buffer, len , 0);
        }
        close(conn);
        close(ss);
        return 0;
    }

      局域网聊天TCP客户端:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    
    #define MYPORT  7000
    #define BUFFER_SIZE 1024
    
    int main()
    {
        ///定义sockfd
        int sock_cli = socket(AF_INET,SOCK_STREAM, 0);
    
        ///定义sockaddr_in
        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(MYPORT);  ///服务器端口
        servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");  ///服务器ip
    
        //连接服务器,成功返回0,错误返回-1
        if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
        {
            perror("connect");
            exit(1);
        }
    
        char sendbuf[BUFFER_SIZE];
        char recvbuf[BUFFER_SIZE];
        while (fgets(sendbuf, sizeof(sendbuf), stdin) != NULL)
        {
            send(sock_cli, sendbuf, strlen(sendbuf),0); ///发送
            if(strcmp(sendbuf,"exit
    ")==0)
                break;
            recv(sock_cli, recvbuf, sizeof(recvbuf),0); ///接收
            fputs(recvbuf, stdout);
    
            memset(sendbuf, 0, sizeof(sendbuf));
            memset(recvbuf, 0, sizeof(recvbuf));
        }
    
        close(sock_cli);
        return 0;
    }

      


      客户端服务端双向异步聊天源码

      以上的局域网聊天应用有一个很重要的缺点, 服务器只能显示客户端发送的消息, 却无法给客户端发送消息, 这个很尴尬;

      通过使用C中的select()函数, 实现一个异步聊天工具:

      异步聊天服务端代码:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    #include <iostream>
    #define PORT 7000
    #define QUEUE 20
    
    int main() {
        fd_set rfds;
        struct timeval tv;
        int retval, maxfd;
        int ss = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in server_sockaddr;
        server_sockaddr.sin_family = AF_INET;
        server_sockaddr.sin_port = htons(PORT);
        //printf("%d
    ",INADDR_ANY);
        server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        if(bind(ss, (struct sockaddr* ) &server_sockaddr, sizeof(server_sockaddr))==-1) {
            perror("bind");
            exit(1);
        }
        if(listen(ss, QUEUE) == -1) {
            perror("listen");
            exit(1);
        }
    
        struct sockaddr_in client_addr;
        socklen_t length = sizeof(client_addr);
        ///成功返回非负描述字,出错返回-1
        int conn = accept(ss, (struct sockaddr*)&client_addr, &length);
        if( conn < 0 ) {
            perror("connect");
            exit(1);
        }
        while(1) {
            /*把可读文件描述符的集合清空*/
            FD_ZERO(&rfds);
            /*把标准输入的文件描述符加入到集合中*/
            FD_SET(0, &rfds);
            maxfd = 0;
            /*把当前连接的文件描述符加入到集合中*/
            FD_SET(conn, &rfds);
            /*找出文件描述符集合中最大的文件描述符*/    
            if(maxfd < conn)
                maxfd = conn;
            /*设置超时时间*/
            tv.tv_sec = 5;
            tv.tv_usec = 0;
            /*等待聊天*/
            retval = select(maxfd+1, &rfds, NULL, NULL, &tv);
            if(retval == -1){
                printf("select出错,客户端程序退出
    ");
                break;
            }else if(retval == 0){
                printf("服务端没有任何输入信息,并且客户端也没有信息到来,waiting...
    ");
                continue;
            }else{
                /*客户端发来了消息*/
                if(FD_ISSET(conn,&rfds)){
                    char buffer[1024];    
                    memset(buffer, 0 ,sizeof(buffer));
                    int len = recv(conn, buffer, sizeof(buffer), 0);
                    if(strcmp(buffer, "exit
    ") == 0) break;
                    printf("%s", buffer);
                    //send(conn, buffer, len , 0);把数据回发给客户端
                }
                /*用户输入信息了,开始处理信息并发送*/
                if(FD_ISSET(0, &rfds)){
                    char buf[1024];
                    fgets(buf, sizeof(buf), stdin);
                    //printf("you are send %s", buf);
                    send(conn, buf, sizeof(buf), 0);    
                }
            }
        }
        close(conn);
        close(ss);
        return 0;
    }

      异步聊天客户端代码:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    
    #define MYPORT  7000
    #define BUFFER_SIZE 1024
    int main()
    {
        int sock_cli;
        fd_set rfds;
        struct timeval tv;
        int retval, maxfd;
    
        ///定义sockfd
        sock_cli = socket(AF_INET,SOCK_STREAM, 0);
        ///定义sockaddr_in
        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(MYPORT);  ///服务器端口
        servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");  ///服务器ip
    
        //连接服务器,成功返回0,错误返回-1
        if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
        {
            perror("connect");
            exit(1);
        }
    
        while(1){
            /*把可读文件描述符的集合清空*/
            FD_ZERO(&rfds);
            /*把标准输入的文件描述符加入到集合中*/
            FD_SET(0, &rfds);
            maxfd = 0;
            /*把当前连接的文件描述符加入到集合中*/
            FD_SET(sock_cli, &rfds);
            /*找出文件描述符集合中最大的文件描述符*/    
            if(maxfd < sock_cli)
                maxfd = sock_cli;
            /*设置超时时间*/
            tv.tv_sec = 5;
            tv.tv_usec = 0;
            /*等待聊天*/
            retval = select(maxfd+1, &rfds, NULL, NULL, &tv);
            if(retval == -1){
                printf("select出错,客户端程序退出
    ");
                break;
            }else if(retval == 0){
                printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...
    ");
                continue;
            }else{
                /*服务器发来了消息*/
                if(FD_ISSET(sock_cli,&rfds)){
                    char recvbuf[BUFFER_SIZE];
                    int len;
                    len = recv(sock_cli, recvbuf, sizeof(recvbuf),0);
                    printf("%s", recvbuf);
                    memset(recvbuf, 0, sizeof(recvbuf));
                }
                /*用户输入信息了,开始处理信息并发送*/
                if(FD_ISSET(0, &rfds)){
                    char sendbuf[BUFFER_SIZE];
                    fgets(sendbuf, sizeof(sendbuf), stdin);
                    send(sock_cli, sendbuf, strlen(sendbuf),0); //发送
                    memset(sendbuf, 0, sizeof(sendbuf));
                }
            }
        }
    
        close(sock_cli);
        return 0;
    }

      局域网内服务端和有限个客户端聊天源码

       以上的局域网聊天只能支持一个用户, 我们还要改改, 必须是支持多用户的聊天室:

      局域网TCP多人聊天服务端代码:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    #include <iostream>
    #include <thread>
    #define PORT 7000
    #define QUEUE 20
    int ss;
    struct sockaddr_in client_addr;
    socklen_t length = sizeof(client_addr);
    int conns[2] = {};
    int z = 0;
    void thread_fn() {
        //成功返回非负描述字,出错返回-1
        int conn = accept(ss, (struct sockaddr*)&client_addr, &length);
        if( conn < 0 ) {
            perror("connect");
            exit(1);
        }
        //把连接保存到临时数组中;
        conns[z] = conn;
        z++;
    
        fd_set rfds;
        struct timeval tv;
        int retval, maxfd;
        while(1) {
            /*把可读文件描述符的集合清空*/
            FD_ZERO(&rfds);
            /*把标准输入的文件描述符加入到集合中*/
            FD_SET(0, &rfds);
            maxfd = 0;
            /*把当前连接的文件描述符加入到集合中*/
            FD_SET(conn, &rfds);
            /*找出文件描述符集合中最大的文件描述符*/    
            if(maxfd < conn)
                maxfd = conn;
            /*设置超时时间*/
            tv.tv_sec = 5;
            tv.tv_usec = 0;
            /*等待聊天*/
            retval = select(maxfd+1, &rfds, NULL, NULL, &tv);
            if(retval == -1){
                printf("select出错,客户端程序退出
    ");
                break;
            }else if(retval == 0){
                printf("服务端没有任何输入信息,并且客户端也没有信息到来,waiting...
    ");
                continue;
            }else{
                /*客户端发来了消息*/
                if(FD_ISSET(conn,&rfds)){
                    char buffer[1024];    
                    memset(buffer, 0 ,sizeof(buffer));
                    int len = recv(conn, buffer, sizeof(buffer), 0);
                    if(strcmp(buffer, "exit
    ") == 0) break;
                    printf("%s", buffer);
                    //send(conn, buffer, len , 0);把数据回发给客户端
                }
                /*用户输入信息了,开始处理信息并发送*/
                if(FD_ISSET(0, &rfds)){
                    char buf[1024];
                    fgets(buf, sizeof(buf), stdin);
                    //printf("you are send %s", buf);
                    for(int i=0; i<z; i++) {
                        send(conns[i], buf, sizeof(buf), 0);
                    }    
                }
            }
        }
        close(conn);
    }
    void thread_select(int conn) {
    }
    int main() {
        ss = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in server_sockaddr;
        server_sockaddr.sin_family = AF_INET;
        server_sockaddr.sin_port = htons(PORT);
        //printf("%d
    ",INADDR_ANY);
        server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);
        if(bind(ss, (struct sockaddr* ) &server_sockaddr, sizeof(server_sockaddr))==-1) {
            perror("bind");
            exit(1);
        }
        if(listen(ss, QUEUE) == -1) {
            perror("listen");
            exit(1);
        }
        std::thread t(thread_fn);
        std::thread t1(thread_fn);
        t.join();
        t1.join();
        close(ss);
        return 0;
    }

      局域网TCP多人聊天客户端代码:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    
    #define MYPORT  7000
    #define BUFFER_SIZE 1024
    int main()
    {
        int sock_cli;
        fd_set rfds;
        struct timeval tv;
        int retval, maxfd;
    
        ///定义sockfd
        sock_cli = socket(AF_INET,SOCK_STREAM, 0);
        ///定义sockaddr_in
        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(MYPORT);  ///服务器端口
        servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");  ///服务器ip
    
        //连接服务器,成功返回0,错误返回-1
        if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
        {
            perror("connect");
            exit(1);
        }
    
        while(1){
            /*把可读文件描述符的集合清空*/
            FD_ZERO(&rfds);
            /*把标准输入的文件描述符加入到集合中*/
            FD_SET(0, &rfds);
            maxfd = 0;
            /*把当前连接的文件描述符加入到集合中*/
            FD_SET(sock_cli, &rfds);
            /*找出文件描述符集合中最大的文件描述符*/    
            if(maxfd < sock_cli)
                maxfd = sock_cli;
            /*设置超时时间*/
            tv.tv_sec = 5;
            tv.tv_usec = 0;
            /*等待聊天*/
            retval = select(maxfd+1, &rfds, NULL, NULL, &tv);
            if(retval == -1){
                printf("select出错,客户端程序退出
    ");
                break;
            }else if(retval == 0){
                printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...
    ");
                continue;
            }else{
                /*服务器发来了消息*/
                if(FD_ISSET(sock_cli,&rfds)){
                    char recvbuf[BUFFER_SIZE];
                    int len;
                    len = recv(sock_cli, recvbuf, sizeof(recvbuf),0);
                    printf("%s", recvbuf);
                    memset(recvbuf, 0, sizeof(recvbuf));
                }
                /*用户输入信息了,开始处理信息并发送*/
                if(FD_ISSET(0, &rfds)){
                    char sendbuf[BUFFER_SIZE];
                    fgets(sendbuf, sizeof(sendbuf), stdin);
                    send(sock_cli, sendbuf, strlen(sendbuf),0); //发送
                    memset(sendbuf, 0, sizeof(sendbuf));
                }
            }
        }
    
        close(sock_cli);
        return 0;
    }

      完美异步聊天服务端和客户端源码

      以上的多客户聊天不是很好, 因为只允许两个客户端连接, 体验非常差, 如果支持无限个客户端聊天的话那该多好啊, 哈哈, 这个也是可以的, 我们只要使用c++的list即可, 它是可以自增的数组(其实算是链表), 引用 头文件<list>即可:

      无限个客户聊天的 服务端代码:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    #include <iostream>
    #include <thread>
    #include <list>
    
    #define PORT 7000
    #define IP "127.0.0.1"
    
    int s;
    struct sockaddr_in servaddr;
    socklen_t len;
    std::list<int> li;
    
    void getConn() {
        while(1){
            int conn = accept(s, (struct sockaddr*)&servaddr, &len);
            li.push_back(conn);
            printf("%d
    ", conn);
        }
    }
    
    void getData() {
        struct timeval tv;
        tv.tv_sec = 2;
        tv.tv_usec = 0;
        while(1) {
            std::list<int>::iterator it;
            for(it=li.begin(); it!=li.end(); ++it){            
                fd_set rfds;    
                FD_ZERO(&rfds);
                int maxfd = 0;
                int retval = 0;
                FD_SET(*it, &rfds);
                if(maxfd < *it){
                    maxfd = *it;
                }
                retval = select(maxfd+1, &rfds, NULL, NULL, &tv);
                if(retval == -1){
                    printf("select error
    ");
                }else if(retval == 0) {
                    //printf("not message
    ");
                }else{
                    char buf[1024];
                    memset(buf, 0 ,sizeof(buf));
                    int len = recv(*it, buf, sizeof(buf), 0);
                    printf("%s", buf);
                }
            }
            sleep(1);
    
        }
    }
    
    void sendMess() {
        while(1) {
            char buf[1024];
            fgets(buf, sizeof(buf), stdin);
            //printf("you are send %s", buf);
            std::list<int>::iterator it;
            for(it=li.begin(); it!=li.end(); ++it){
                send(*it, buf, sizeof(buf), 0);
            }
        }
    }
    
    int main() {
        //new socket
        s = socket(AF_INET, SOCK_STREAM, 0);
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(PORT);
        servaddr.sin_addr.s_addr = inet_addr(IP);
        if(bind(s, (struct sockaddr* ) &servaddr, sizeof(servaddr))==-1) {
            perror("bind");
            exit(1);
        }
        if(listen(s, 20) == -1) {
            perror("listen");
            exit(1);
        }
        len = sizeof(servaddr);
    
        //thread : while ==>> accpet
        std::thread t(getConn);
        t.detach();
        //printf("done
    ");
        //thread : input ==>> send
        std::thread t1(sendMess);
        t1.detach();
        //thread : recv ==>> show
        std::thread t2(getData);
        t2.detach();
        while(1){
    
        }
        return 0;
    }

      无限个客户端连接的客户端代码:

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <stdio.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <fcntl.h>
    #include <sys/shm.h>
    
    #define MYPORT  7000
    #define BUFFER_SIZE 1024
    int main()
    {
        int sock_cli;
        fd_set rfds;
        struct timeval tv;
        int retval, maxfd;
    
        ///定义sockfd
        sock_cli = socket(AF_INET,SOCK_STREAM, 0);
        ///定义sockaddr_in
        struct sockaddr_in servaddr;
        memset(&servaddr, 0, sizeof(servaddr));
        servaddr.sin_family = AF_INET;
        servaddr.sin_port = htons(MYPORT);  ///服务器端口
        servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");  ///服务器ip
    
        //连接服务器,成功返回0,错误返回-1
        if (connect(sock_cli, (struct sockaddr *)&servaddr, sizeof(servaddr)) < 0)
        {
            perror("connect");
            exit(1);
        }
    
        while(1){
            /*把可读文件描述符的集合清空*/
            FD_ZERO(&rfds);
            /*把标准输入的文件描述符加入到集合中*/
            FD_SET(0, &rfds);
            maxfd = 0;
            /*把当前连接的文件描述符加入到集合中*/
            FD_SET(sock_cli, &rfds);
            /*找出文件描述符集合中最大的文件描述符*/    
            if(maxfd < sock_cli)
                maxfd = sock_cli;
            /*设置超时时间*/
            tv.tv_sec = 5;
            tv.tv_usec = 0;
            /*等待聊天*/
            retval = select(maxfd+1, &rfds, NULL, NULL, &tv);
            if(retval == -1){
                printf("select出错,客户端程序退出
    ");
                break;
            }else if(retval == 0){
                printf("客户端没有任何输入信息,并且服务器也没有信息到来,waiting...
    ");
                continue;
            }else{
                /*服务器发来了消息*/
                if(FD_ISSET(sock_cli,&rfds)){
                    char recvbuf[BUFFER_SIZE];
                    int len;
                    len = recv(sock_cli, recvbuf, sizeof(recvbuf),0);
                    printf("%s", recvbuf);
                    memset(recvbuf, 0, sizeof(recvbuf));
                }
                /*用户输入信息了,开始处理信息并发送*/
                if(FD_ISSET(0, &rfds)){
                    char sendbuf[BUFFER_SIZE];
                    fgets(sendbuf, sizeof(sendbuf), stdin);
                    send(sock_cli, sendbuf, strlen(sendbuf),0); //发送
                    memset(sendbuf, 0, sizeof(sendbuf));
                }
            }
        }
    
        close(sock_cli);
        return 0;
    }

      局域网通过UDP实现服务端和客户端的通信, UDP的服务端不需要执行listen函数accept函数

    #include <sys/types.h>
    #include <sys/socket.h>
    #include <netinet/in.h>
    #include <string.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <unistd.h>
    #define PORT_SERV 8888
    #define BUFF_LEN 256
    void udpserv_echo(int s, struct sockaddr* client);
    int main() {
        int s;
        struct sockaddr_in addr_serv, addr_clie;
        s = socket(AF_INET, SOCK_DGRAM, 0);
        memset(&addr_serv, 0 , sizeof(addr_serv));
        addr_serv.sin_family = AF_INET;
        addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
        addr_serv.sin_port = htons(PORT_SERV);
        bind(s, (struct sockaddr*)&addr_serv, sizeof(addr_serv));
        udpserv_echo(s, (struct sockaddr*)&addr_clie);
        return 0;
    }
    void udpserv_echo(int s, struct sockaddr* client) {
        int n;
        char buff[BUFF_LEN];
        int len;
        //printf("%p
    ",&recvfrom);
        while(1) {
            socklen_t length = sizeof(client);
            n = recvfrom(s, buff, BUFF_LEN, 0 , client, &length);
            printf("%s
    ", buff);
            //strcpy(buff, "nice to see you");
            sendto(s, buff, n, 0, client, len);
        }
    }

      UDP客户端代码, UDP客户端不需要connect函数, 但是执行sendto的时候需要指定 sockfd描述符:

    #include <netinet/in.h>
    #include <string.h>
    #include <fcntl.h>
    #include <stdio.h>
    #include <unistd.h>
    #include <arpa/inet.h>
    
    #define PORT_SERV 8888
    #define BUFF_LEN 256
    void udpclient_echo(int s, struct sockaddr* serv) {
        char buff[BUFF_LEN];
        int len = sizeof(*serv);
        while(fgets(buff, BUFF_LEN, stdin)!=NULL) {
            sendto(s, buff, BUFF_LEN, 0, serv, len);       
        }
    }
    int main(int argc , char ** argv) {
        int s;
        struct sockaddr_in addr_serv;
        s = socket(AF_INET, SOCK_DGRAM, 0);
        memset(&addr_serv, 0 , sizeof(addr_serv));
        addr_serv.sin_family = AF_INET;
        //addr_serv.sin_addr.s_addr = htonl(INADDR_ANY);
        addr_serv.sin_addr.s_addr = inet_addr(argv[1]);
        addr_serv.sin_port = htons(PORT_SERV);
        udpclient_echo(s, (struct sockaddr*)&addr_serv);
        return 0;
    }

      获取当前进程的ID:

    #include <sys/types.h>
    #include <unistd.h>
    #include <stdio.h>
    int main(void) {
        pid_t pid,ppid;
        pid = getpid();
        ppid = getppid();
        printf("pid is %d;
    ppid is %d; 
    ",pid, ppid);
        return 0;
    }

      system语句的使用:

    #include <stdlib.h>
    #include <stdio.h>
    int main(void) {
        int ret;
        ret = system("ping www.baidu.com");
        printf("%d
    ", ret);
        return 0;
    }

      C++定时器

      定时器, 这个是c++的语法, c的标准库中没有定时器:

    #include <stdio.h>        //printf()
    #include <unistd.h>        //pause()
    #include <signal.h>        //signal()
    #include <string.h>        //memset()
    #include <sys/time.h>    //struct itimerval, setitimer()
    
    static int count = 0;
    
    void printMes(int signo)
    {
        printf("Get a SIGALRM, %d counts!
    ", ++count);
    }
    
    int main()
    {
        int res = 0;
        struct itimerval tick;
        
        signal(SIGALRM, printMes);
        memset(&tick, 0, sizeof(tick));
    
        //Timeout to run first time
        tick.it_value.tv_sec = 1;
        tick.it_value.tv_usec = 0;
    
        //After first, the Interval time for clock
        tick.it_interval.tv_sec = 1;
        tick.it_interval.tv_usec = 0;
        setitimer(ITIMER_REAL, &tick, NULL);
        //if(setitimer(ITIMER_REAL, &tick, NULL) < 0)
                //printf("Set timer failed!
    ");
    
        //When get a SIGALRM, the main process will enter another loop for pause()
        while(1)
        {
        }
        return 0;
    } 

      select的使用,通过select可以实现定时器:

    static void sleep_ms(unsigned int secs){
        struct timeval tval;
        tval.tv_sec=secs/1000;
        tval.tv_usec=(secs*1000)%1000000;
        select(0,NULL,NULL,NULL,&tval);
    }

      select异步代码

      通过select,实现socket可读或者可写的时候,然后再搞事情:

    #include <stdio.h>
    #include <sys/time.h>
    #include <sys/types.h>
    #include <unistd.h>
    int main() {
        while(1) {
            fd_set rd;
            struct timeval tv;
            int err;
    
            FD_ZERO(&rd);
            FD_SET(0, &rd);
    
            tv.tv_sec = 5;
            tv.tv_usec = 0;
            err = select(1, &rd, NULL, NULL, &tv);
            if(err == -1) {
                perror("select error()
    ");
            }else if(err == 0) {
                printf("no data is avaliable now
    ");
            }else{
                if(FD_ISSET(0, &rd)) {
                    char buf[1024];
                    fgets(buf, sizeof(buf), stdin);
                    printf("%s",buf);
                }
            }
        }
        return 0;
    }

      pthead多线程

      没有参数的多线程 ,假设文件名字为:ph.c ,那么要通过 gcc ph.c -o ph -w -lphread ,进行编译:

    #include <stdio.h>
    #include <string.h>
    #include <pthread.h>
    
    void *pfn() {
        printf("run
    ");
    }
    
    void main(int argc , char *argv[] ) {
        pthread_t pid, pid2;
        pthread_create(&pid, NULL, pfn, NULL);
        pthread_join(pid, NULL);
    }

      pthead多线程编程, 使用pthead实现子程, 并给子程传递参数:

    #include <stdio.h>
    #include <pthread.h>
    #include <unistd.h>
    #include <string.h>
    #include <stdlib.h>
    #include <iostream>
    
    void* start(void* args) {
        printf("sub thread ; the args is %d
    ", *((int *)args));
        return NULL;
    }
    int main(void) {
        pthread_t pt;
        int ret = -1;
        int times = 3;
        int run = 2;
        ret = pthread_create(&pt, NULL, start, &run);
        if(ret != 0) {
            printf("create error
    ");
            return 1;
        }
        usleep(1);
        printf("main thread
    ");
        pthread_join(pt, NULL);
        return 0;
    }

      获取指定网卡的MAC地址和IP:

    #include <net/ethernet.h>
    #include <stdio.h>
    #include <sys/socket.h>
    #include <linux/if_packet.h>
    #include <net/if.h>
    #include <stdlib.h>
    #include <string.h>
    #include <fcntl.h>
    #include <unistd.h>
    #include <sys/ioctl.h>
    #include <netinet/ether.h>
    #include <netinet/in.h>
    #include <arpa/inet.h>
    
    void getMac(char *MAC, char *str) {
       char ifPath[256]="/sys/class/net/"; //默认网卡路径
        strcat(ifPath , str);
        strcat(ifPath ,"/address");
        //打开这个设备
        FILE *ff = fopen(ifPath,"r");
        fread(MAC,1, 17, ff);
        fclose(ff);
    }
    //根据网卡获取ip的通用函数
    void getIp(unsigned char *ip, char *itf) {
        int fd;
        struct ifreq ifr;
        in_addr tIP ;
    
        fd = socket(AF_INET, SOCK_DGRAM, 0);    //using ioctl get IP address
        ifr.ifr_addr.sa_family = AF_INET;
        strcpy(ifr.ifr_name , (char*)itf);
        ioctl(fd, SIOCGIFADDR, &ifr);
    
        close(fd);
    
        tIP =((struct sockaddr_in *)&ifr.ifr_addr)->sin_addr;
        memcpy((char*)ip , &tIP ,sizeof(in_addr));
        printf("ip is %s", inet_ntoa(tIP));
    }
    
    int main(int argc, char *argv[]) {
        struct sockaddr_ll device;
        char NetInterface[10];
        strcpy(NetInterface, argv[1]);
        int index = if_nametoindex ((const char*)NetInterface);
        printf("index is %d
    ", index);
    
        //get MAC, 要设置初始值
        char MAC[18]={0};
        char end[] = "0";
        getMac(MAC, argv[1]);
        printf("%s
    ", MAC);
    
        unsigned char ip[4];
        getIp(ip, argv[1]);
        printf("
    ");
        return 0;
    }

      C, fork语句的使用, fork返回值为0时说明运行在拷贝线程中:

    #include <stdio.h>
    #include <stdlib.h>
    #include <unistd.h>
    #include <sys/types.h>
    int main() {
        pid_t pid;
        pid = fork();
        if( -1 == pid ) {
            printf("error 
    ");
        }else if( pid ==0 ) {
            printf(" fork value %d ; parent id : %d ; fork id : %d
     ", pid, getppid(), getpid());
        }else{
            printf(" run in parent scope, pid is %d 
    ", getpid());
        }
        return 0;
    }

      通过使用fork,可以简化服务端的代码, 局域网聊天服务端代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <errno.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    
    const int MAX_LINE = 2048;
    const int PORT = 6000;
    const int BACKLOG = 10;
    const int LISTENQ = 6666;
    const int MAX_CONNECT = 20;
    
    int main() {
        struct sockaddr_in serAddr, cliAddr;
        int listenFd, connFd;
        pid_t childPid;
        char buf[MAX_LINE];
        socklen_t client;
    
        listenFd = socket(AF_INET, SOCK_STREAM, 0);
        if(listenFd < 0){
            perror("socket error");
            exit(1);
    
        }
        bzero(&serAddr, sizeof(serAddr));
        serAddr.sin_family = AF_INET;
        serAddr.sin_addr.s_addr = htonl(INADDR_ANY);
        serAddr.sin_port = htons(PORT);
        if(bind(listenFd, (struct sockaddr*)&serAddr, sizeof(serAddr)) < 0) {
            perror("bind error");
            exit(1);
        };
        if(listen(listenFd, LISTENQ) < 0) {
            perror("listen error");
            exit(1);
        };
            printf("data");
        while(true) {
            client = sizeof(cliAddr);
            connFd = accept(listenFd, (struct sockaddr*)&cliAddr, &client);
            if(connFd < 0) {
                perror("accept error");
                exit(1);
            }
            childPid =fork();
            if(childPid == 0) {
                close(listenFd);
                char buf[MAX_LINE];
                while(read(connFd, buf, MAX_LINE) > 0) {
                    printf("data is %s", buf);
                    memset(buf, 0 ,sizeof(buf));
                };
            }
        }
        close(listenFd);
        return 0;
    }

      客户端代码:

    #include <stdio.h>
    #include <stdlib.h>
    #include <string.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <unistd.h>
    #include <errno.h>
    #include <netinet/in.h>
    #include <netdb.h>
    #include <arpa/inet.h>
    
    const int MAX_LINE = 2048;
    const int PORT = 6000;
    const int BACKLOG = 10;
    const int LISTENQ = 6666;
    const int MAX_CONNECT = 20;
    
    int main(int argc , char **argv) {
        int sockFd;
        struct sockaddr_in serAddr;
        if( argc != 2) {
            perror("args error");
            exit(1);
        }
        sockFd = socket(AF_INET, SOCK_STREAM, 0);
        if(sockFd < 0) {
            perror("socket error");
            exit(1);
        }
        bzero(&serAddr, sizeof(serAddr));
        serAddr.sin_family = AF_INET;
        serAddr.sin_port = htons(PORT);
        printf("%s",argv[0]);
        //serAddr.sin_addr.s_addr = inet_addr(argv[1]);
        if(inet_pton(AF_INET , argv[1] , &serAddr.sin_addr) < 0)
        {
            printf("inet_pton error for %s
    ",argv[1]);
            exit(1);
        }
        if(connect(sockFd, (struct sockaddr*)&serAddr, sizeof(serAddr)) < 0) {
            perror("connect error");
            exit(1);
        };
        char sendLine[MAX_LINE];
        while(fgets(sendLine, MAX_LINE, stdin)!=NULL) {
            write(sockFd, sendLine, strlen(sendLine));
        }
        close(sockFd);
        return 0;
    }

       socket服务端:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <string.h>
    
    #define QUEUE 10
    #define SIZE 256
    
    int main() {
        //sock fd 
        int fd;
        struct sockaddr_in saddr, caddr;
        fd = socket(AF_INET, SOCK_STREAM, 0);
        if( fd<0 ){
            perror("socket error");
            exit(1);
        }
        bzero(&saddr , sizeof(saddr));
        bzero(&caddr , sizeof(caddr));
        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(2000);
        saddr.sin_addr.s_addr = htonl(INADDR_ANY);
    
        //bind 
        int bfd = bind(fd, (struct sockaddr *)&saddr, sizeof(saddr));
        if( bfd<0 ){
            perror("bind error");
            exit(1);
        }
        //listen
        int lfd = listen(fd, QUEUE);
        if( lfd<0 ){
            perror("listen error");
            exit(1);
        }
        //accept
        socklen_t len = sizeof(caddr);
        int conn = accept(fd, (struct sockaddr *)&caddr, &len);
        if(conn < 0){
            perror("conn error");
            exit(1);
        }
        char buf[SIZE];
    
        while(read(conn, buf, SIZE) > 0) {
            //read
            printf("%s", buf);
            bzero(buf, SIZE);
        }
    
    
        close(fd);
        return 0;
    }
    View Code

      socket客户端:

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/socket.h>
    #include <sys/types.h>
    #include <arpa/inet.h>
    #include <unistd.h>
    #include <netdb.h>
    #include <string.h>
    
    #define SIZE 256
    
    int main() {
        int fd;
        fd = socket(AF_INET, SOCK_STREAM, 0);
        struct sockaddr_in saddr;
        bzero(&saddr, sizeof(saddr));
        saddr.sin_family = AF_INET;
        saddr.sin_port = htons(2000);
        saddr.sin_addr.s_addr = inet_addr("127.0.0.1");
    
        int conn;
        conn = connect(fd, (struct sockaddr*)&saddr, sizeof(saddr));
        if( conn<0 ) {
            perror("error");
            exit(1);
        }
        char buf[SIZE];
        while(fgets(buf, SIZE, stdin)!=NULL) {
            printf("%s", buf);
            write(fd, buf, SIZE);
            bzero(buf, SIZE);
        }
        return 0;
    }
    View Code

      参考

      c++中Socket通信函数之select : http://blog.csdn.net/piaojun_pj/article/details/5991968/

      EOF

    作者: NONO
    出处:http://www.cnblogs.com/diligenceday/
    QQ:287101329
    微信:18101055830 

  • 相关阅读:
    Python中os与sys两模块的区别
    单线程爬取图片
    linux下glances服务器监控工具
    python中的join()函数的用法
    python的exec、eval详解
    mongodb启动不了解决方法
    生产者和消费者(.net实现)
    IOS开发--第一阶段--导行(1)(基本概念)
    12.26 linux基本操作指令
    12.25
  • 原文地址:https://www.cnblogs.com/diligenceday/p/6241021.html
Copyright © 2011-2022 走看看