自学内容网 自学内容网

十八、Linux网络编程(二)

3.并发服务器

1.TCP多线程并发服务器

service_thread.c:

#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <pthread.h>

#define QUIT_STR "QUIT"
#define BUFSIZE 1024
#define backlog 5
#define SERV_IP 5001
#define SERV_IP_ADDR "192.168.157.129"

void* client_data_handle(void *arg);
int main()
{
        int fd = -1;
        struct sockaddr_in sin;
        //1.socket
        fd = socket(AF_INET,SOCK_STREAM,0);
        if(fd < 0)
        {
                perror("socket");
                exit(1);
        }
        bzero(&sin,sizeof(sin));

        sin.sin_family = AF_INET;
        sin.sin_port = htons(SERV_IP);
        //      sin.sin_addr.s_addr = inet_addr(SERV_IP_ADDR);
        sin.sin_addr.s_addr = INADDR_ANY;
        /*      if(inet_pton(AF_INET,SERV_IP_ADDR,sin.(void *)&sin_addr.s_addr) != 1)
                {
                perror("inet_pton");
                exit(1);
                }
                */
        //2.bind
        if(bind(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
        {
                perror("bind");
                exit(1);
        }

        //3.listen
        if(listen(fd,backlog) < 0)
        {
                perror("listen");
                exit(1);
        }
        //4.accept
        /*
           int newfd = -1;
           newfd = accept(fd,NULL,NULL);
           if(newfd < 0)
           {
           perror("accept");
           exit(1);
           }
           */
        pthread_t tid;

        int newfd = -1;
        struct sockaddr_in cin;
        socklen_t addrlen = sizeof(cin);
        while(1)
        {
                newfd = accept(fd,(struct sockaddr *)&cin,&addrlen);
                if(newfd < 0)
                {
                        perror("accept");
                        exit(1);
                }
                char ipv4_addr[16];
                if(!inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin)))
                {
                        perror("inet_ntop");
                        exit(1);
                }
                printf("client : (%s,%d) is connected!\n",ipv4_addr,ntohs(cin.sin_port));
                pthread_create(&tid,NULL,client_data_handle,(void *)&newfd);
        }
        close(fd);
        return 0;

}

void* client_data_handle(void *arg)
{
        int newfd = *(int *)arg;
        char buf[BUFSIZE];
        int ret = -1;
        printf("handle thread :newfd = %d\n ",newfd);
        while(1)
        {
                do{
                        bzero(buf,BUFSIZE);
                        ret = read(newfd,buf,BUFSIZE-1);
                }while(ret < 1);
                if(ret < 0)
                {
                        exit(1);
                }
                if(!ret) //ret = 0
                {
                        break;
                }
                printf("receive data is %s\n",buf);
                if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
                {
                        printf("client is exit\n");
                        break;
                }
        }
        close(newfd);
        return NULL;
}

client_thread.c:

#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

//  ./client 192.168.157.129 5001

#define QUIT_STR "QUIT"
#define BUFSIZE 1024
#define SERV_IP 5001
#define SERV_IP_ADDR "192.168.157.129"
int main(int argc,char **argv)
{
        int fd = -1;

        int port = -1;
        port = atoi(argv[2]);

        struct sockaddr_in sin;
        //1.socket
        fd = socket(AF_INET,SOCK_STREAM,0);
        if(fd < 0)
        {
                perror("socket");
                exit(1);
        }
        bzero(&sin,sizeof(sin));

        sin.sin_family = AF_INET;
        sin.sin_port = htons(port);
        sin.sin_addr.s_addr = inet_addr(argv[1]);
        //2.connect
        if(connect(fd,(struct sockaddr *)&sin,sizeof(sin)) < 0)
        {
                perror("connect");
                exit(1);
        }
        //3.write
        char buf[BUFSIZE];
        while(1)
        {
                bzero(buf,BUFSIZE);
                if(fgets(buf,BUFSIZE-1,stdin) == NULL)
                {
                        continue;
                }
                write(fd,buf,strlen(buf));
                if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
                {
                        break;
                }
        }
        return 0;
}

2.TCP多进程并发服务器

service_pro.c:

#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <signal.h>
#include <sys/wait.h>

#define QUIT_STR "QUIT"
#define BUFSIZE 1024
#define backlog 5
#define SERV_IP 5001
#define SERV_IP_ADDR "192.168.157.129"

void child_data_handle(int signum)
{
        if(SIGCHLD == signum)
        {
                waitpid(-1,NULL,WNOHANG);
        }
}
void* client_data_handle(void *arg);
int main()
{
        signal(SIGCHLD,child_data_handle);
        int fd = -1;
        struct sockaddr_in sin;
        //1.socket
        fd = socket(AF_INET,SOCK_STREAM,0);
        bzero(&sin,sizeof(sin));

        sin.sin_family = AF_INET;
        sin.sin_port = htons(SERV_IP);
        //      sin.sin_addr.s_addr = inet_addr(SERV_IP_ADDR);
        sin.sin_addr.s_addr = INADDR_ANY;
        /*      if(inet_pton(AF_INET,SERV_IP_ADDR,sin.(void *)&sin_addr.s_addr) != 1)
                {
                perror("inet_pton");
                exit(1);
                }
                */
        //2.bind
        bind(fd,(struct sockaddr *)&sin,sizeof(sin));

        //3.listen
        listen(fd,backlog);

        //4.accept
        pid_t pid;
        int newfd = -1;
        struct sockaddr_in cin;
        socklen_t addrlen = sizeof(cin);
        while(1)
        {
                newfd = accept(fd,(struct sockaddr *)&cin,&addrlen);
                pid = fork();
                if(pid > 0)
                {
                        close(newfd);
                }
                if(pid == 0)
                {
                        char ipv4_addr[16];
                        inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin));
                        printf("client : (%s,%d) is connected!\n",ipv4_addr,ntohs(cin.sin_port));
                        client_data_handle(&newfd);
                        close(fd);
                }
        }
        return 0;

}

void* client_data_handle(void *arg)
{
        int newfd = *(int *)arg;
        char buf[BUFSIZE];
        int ret = -1;
        printf("child handle porcess :newfd = %d\n ",newfd);
        while(1)
        {
                do{
                        bzero(buf,BUFSIZE);
                        ret = read(newfd,buf,BUFSIZE-1);
                }while(ret < 1);
                if(ret < 0)
                {
                        exit(1);
                }
                if(!ret) //ret = 0
                {
                        break;
                }
                printf("receive data is %s\n",buf);
                if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
                {
                        printf("client is exit\n");
                        break;
                }
        }
        close(newfd);
        return NULL;
}

client_pro.c不变

额外:TCPAPI补充

1.send()

ssize_t send(int sockfd,

                     const void *buf,

                     size_t len,

                     int flags

                     );

参数:

        sockfd:socket函数返回的fd

        buf:发送缓冲区首地址

        len:发送的字节

        flags:发送方式(通常为0),作用和write一样

                MSG_DONTWAIT:非阻塞

                MSG_OOB:用于TCP类型的带外数据(out of band

返回值:

成功:实际发送的字节数

失败:-1,并设置errno

2.recv()

ssize_t recv(int sockfd,

                    void *buf,

                    size_t len,

                    int flags

                    );

        flags:一般填0,作用和read一样

特殊的标志:

        MSG_DONTWAIT:非阻塞

        MSG_OOB:读取带外数据

        MSG_PEEK:流

 4.UDP编程

receivefrom():阻塞等待客户端数据

ssize_t recvfrom(int sockfd, void *buf, size_t len, int flags,
                        struct sockaddr *src_addr, socklen_t *addrlen);

sendto():指定服务器的IP地址和端口号,要发送的数据

ssize_t sendto(int sockfd, const void *buf, size_t len, int flags,
                      const struct sockaddr *dest_addr, socklen_t addrlen);

无连接尽力传输,UDP是不可靠传输

实时的音视频传输,DNS域名解析包

service_udp.c :

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <strings.h>
#include <sys/types.h>          /* See NOTES */
#include <sys/socket.h>
#include <arpa/inet.h>

#define SEVR_PORT 5001
#define QUIT_STR "QUIT"
#define BUFSIZE 1024
int main()
{
        //socket
        int fd = -1;
        fd = socket(AF_INET,SOCK_DGRAM,0);

        int b_reuser = 1;

        //addr
        setsockopt(fd,SOL_SOCKET,SO_REUSEADDR,&b_reuser,sizeof(int));

        //bind
        struct sockaddr_in sin;
        bzero(&sin,sizeof(sin));
        sin.sin_family = AF_INET;
        sin.sin_port = htons(SEVR_PORT);
        sin.sin_addr.s_addr = htonl(INADDR_ANY);

        bind(fd,(struct sockaddr*)&sin,sizeof(sin));

        //recvfrom
        char buf[BUFSIZE];
        struct sockaddr_in cin;
        socklen_t addrlen = sizeof(cin);
        while(1)
        {
                bzero(buf,BUFSIZE);
                recvfrom(fd,buf,BUFSIZE-1,0,(struct sockaddr *)&cin,&addrlen);
                char ipv4_addr[16];
                inet_ntop(AF_INET,(void *)&cin.sin_addr,ipv4_addr,sizeof(cin));
                printf("reveive from (%s,%d),data is %s\n",ipv4_addr,ntohs(cin.sin_port),buf);
                if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
                {
                        printf("client (%s,%d) is exit",ipv4_addr,ntohs(cin.sin_port));
                }
        }
        close(fd);
        return 0;
}

client_udp.c:

#include <stdio.h>
#include <sys/types.h>
#include <string.h>
#include <strings.h>
#include <stdlib.h>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>

//  ./client 192.168.157.129 5001

#define QUIT_STR "QUIT"
#define BUFSIZE 1024
#define SERV_IP 5001
#define SERV_IP_ADDR "192.168.157.129"
int main(int argc,char **argv)
{
        int fd = -1;

        int port = -1;
        port = atoi(argv[2]);

        struct sockaddr_in sin;
        //1.socket
        fd = socket(AF_INET,SOCK_STREAM,0);
        bzero(&sin,sizeof(sin));

        sin.sin_family = AF_INET;
        sin.sin_port = htons(port);
        sin.sin_addr.s_addr = inet_addr(argv[1]);
        //2.sendto
        char buf[BUFSIZE];
        while(1)
        {
                if(fgets(buf,BUFSIZE-1,stdin) == NULL)
                {
                        continue;
                }
                sendto(fd,buf,strlen(buf),0,(struct sockaddr*)&sin,sizeof(sin));
                if(!strncasecmp(buf,QUIT_STR,strlen(QUIT_STR)))
                {
                        break;
                }
        }
        close(fd);
        return 0;
}


原文地址:https://blog.csdn.net/2402_87254779/article/details/143762075

免责声明:本站文章内容转载自网络资源,如本站内容侵犯了原著者的合法权益,可联系本站删除。更多内容请关注自学内容网(zxcms.com)!