linux下 socket tcp Server c语言编写(分别实现单进程,多进程,多线程)

来源:互联网 发布:网络接单平台 编辑:程序博客网 时间:2024/06/06 10:53

TCP 迭代服务器接受一个客户端的连接,然后处理,完成了这个客户的所有请求后,断开连接。TCP 迭代服务器一次只能处理一个客户端的请求,只有在这个客户的所有请求满足后,服务器才可以继续后面的请求。如果有一个客户端占住服务器不放时,其它的客户机都不能工作了,因此,TCP 服务器一般很少用迭代服务器模型的。

tcp服务器端框架
1.创建tcp套接字
2. 绑定套接字
3. 监听套接字
4. 调用accept()阻塞等待
5. 处理客户端的请求
6. 关闭连接套接字
7. 关闭监听套接字
tcp客户端框架
1.创建tcp套接字
2.调用connect()连接服务器
3.处理服务器端返回的信息
由于客户端不需要固定的端⼜号,因此不必调⽤bind(),客户端的端⼜号由内核⾃动分配。注意, 客户端不是不允许调⽤bind(),只是没有必要调⽤bind()固定⼀个端⼜号,服务器也不是必须调⽤bind(),但如果服务器不调⽤bind(),内核会⾃动给服务器分配监听端⼜,每次启动服务器时端⼜ 号都不⼀样,客户端要连接服务器就会遇到⿇烦。
单进程
server.c

#include<stdio.h>#include<sys/socket.h>#include<netinet/in.h>#include<errno.h>#include<unistd.h>#include<string.h>#include<sys/types.h>#include<arpa/inet.h>#include<netinet/in.h>#define _PORT_ 9999#define _BACKLOG_ 10int main(){                                                                                                              int sock=socket(AF_INET,SOCK_STREAM,0);    if(sock<0)    {        printf("socket()\n");    }    struct sockaddr_in server_socket;    struct sockaddr_in socket;    bzero(&server_socket,sizeof(server_socket));    server_socket.sin_family=AF_INET;    server_socket.sin_addr.s_addr=htonl(INADDR_ANY);    server_socket.sin_port=htons(_PORT_);    if(bind(sock,(struct sockaddr*)&server_socket,sizeof(struct sockaddr_in))<0)    {        printf("bind()\n");        close(sock);        return 1;    }    if(listen(sock,_BACKLOG_)<0)    {        printf("listen()\n");        close(sock);        return 2;    }    printf("success\n");       for(;;)    {        socklen_t len=0;        int client_sock=accept(sock,(struct sockaddr*)&socket,&len);        if(client_sock<0)        {            printf("accept()\n");            return 3;        }        char buf_ip[INET_ADDRSTRLEN];        memset(buf_ip,'\0',sizeof(buf_ip));        inet_ntop(AF_INET,&socket.sin_addr,buf_ip,sizeof(buf_ip));        printf("get connect\n");        while(1)        {            char buf[1024];            memset(buf,'\0',sizeof(buf));            read(client_sock,buf,sizeof(buf));   printf("client:# %s\n",buf);            printf("server:$ ");            memset(buf,'\0',sizeof(buf));            fgets(buf,sizeof(buf),stdin);            buf[strlen(buf)-1]='\0';            if(strncasecmp(buf,"quit",4)==0)            {                printf("quit\n");                break;            }            write(client_sock,buf,strlen(buf)+1);            printf("wait...\n");        }        close(client_sock);    }    close(sock);    return 0;}                      

多进程
怎么将单进程的代码改为多进程的代码呢?
调用fork()函数,创建子进程,将所有的客户端的请求处理的内容都放在子进程中处理。
在 Linux 环境下多进程的应用很多,其中最主要的就是网络/客户服务器。多进程服务器是当客户有请求时,服务器用一个子进程来处理客户请求。父进程继续等待其它客户的请求。这种方法的优点是当客户有请求时,服务器能及时处理客户,特别是在客户服务器交互系统中。对于一个 TCP 服务器,客户与服务器的连接可能并不马上关闭,可能会等到客户提交某些数据后再关闭,这段时间服务器端的进程会阻塞,所以这时操作系统可能调度其它客户服务进程,这比起循环服务器大大提高了服务性能。
server.c

#include<stdio.h>#include<sys/socket.h>#include<netinet/in.h>#include<errno.h>#include<unistd.h>#include<string.h>#include<sys/types.h>                                                                                      #include<arpa/inet.h>#include<netinet/in.h>#define _PORT_ 9999#define _BACKLOG_ 10int main(){    int sock=socket(AF_INET,SOCK_STREAM,0);    if(sock<0)    {        printf("socket()\n");    }    struct sockaddr_in server_socket;    struct sockaddr_in socket;    bzero(&server_socket,sizeof(server_socket));    server_socket.sin_family=AF_INET; server_socket.sin_addr.s_addr=htonl(INADDR_ANY);    server_socket.sin_port=htons(_PORT_);    if(bind(sock,(struct sockaddr*)&server_socket,sizeof(struct sockaddr_in))<0)    {        printf("bind()\n");        close(sock);        return 1;    }    if(listen(sock,_BACKLOG_)<0)    {        printf("listen()\n");        close(sock);        return 2;    }    printf("success\n");    for(;;)    {        socklen_t len=0;        int client_sock=accept(sock,(struct sockaddr*)&socket,&len);        if(client_sock<0)        {                     printf("accept()\n");            return 3;        }        char buf_ip[INET_ADDRSTRLEN];        memset(buf_ip,'\0',sizeof(buf_ip));        inet_ntop(AF_INET,&socket.sin_addr,buf_ip,sizeof(buf_ip));        printf("get connect\n");        pid_t fd=fork();        if(fd<0)            printf("fork()\n");        if(fd==0)        {          close(sock);//关闭监听套接字                     printf("port=%d,ip=%s\n",ntohs(socket.sin_port),buf_ip);            while(1)           {               char buf[1024];               memset(buf,'\0',sizeof(buf));               read(client_sock,buf,sizeof(buf));                      printf("client:# %s\n",buf);               printf("server:$ ");               memset(buf,'\0',sizeof(buf));               fgets(buf,sizeof(buf),stdin);               buf[strlen(buf)-1]='\0';               if(strncasecmp(buf,"quit",4)==0)               {                   printf("quit\n");                   break;               }               write(client_sock,buf,strlen(buf)+1);               printf("wait...\n");           }    close(fd);      }        else if(fd>0)        {            close(fd);                        }    }    close(sock);    return 0;}

多线程
多线程和多进程的处理方式类似,都是创建一个新的线程,客户端有请求时,用新创建的线程处理。

#include<stdio.h>#include<sys/socket.h>#include<netinet/in.h>#include<errno.h>#include<unistd.h>#include<string.h>#include<sys/types.h>#include<arpa/inet.h>#include<netinet/in.h>#define _PORT_ 9999#define _BACKLOG_ 10void *fun(void* arg){    int client_sock = (int)arg;        while(1)        {              char buf[1024];            memset(buf,'\0',sizeof(buf));            read(client_sock,buf,sizeof(buf));            printf("client:# %s\n",buf);            printf("server:$ ");            memset(buf,'\0',sizeof(buf));            fgets(buf,sizeof(buf),stdin);            buf[strlen(buf)-1]='\0';            if(strncasecmp(buf,"quit",4)==0)            {                printf("quit\n");                break;            }            write(client_sock,buf,strlen(buf)+1);            printf("wait...\n");        }    close(client_sock);}int main(){    int sock=socket(AF_INET,SOCK_STREAM,0);    if(sock<0)    {        printf("socket()\n");    }    struct sockaddr_in server_socket;    struct sockaddr_in socket;     pthread_t thread_id;      bzero(&server_socket,sizeof(server_socket));    server_socket.sin_family=AF_INET;    server_socket.sin_addr.s_addr=htonl(INADDR_ANY);    server_socket.sin_port=htons(_PORT_);    if(bind(sock,(struct sockaddr*)&server_socket,sizeof(struct sockaddr_in))<0)    {        printf("bind()\n");        close(sock);        return 1;    }    if(listen(sock,_BACKLOG_)<0)    {        printf("listen()\n");        close(sock);        return 2;    }    printf("success\n");    for(;;)    {        socklen_t len=0;        int client_sock=accept(sock,(struct sockaddr*)&socket,&len);        if(client_sock<0)        {            printf("accept()\n");            return 3;        }        char buf_ip[INET_ADDRSTRLEN];        memset(buf_ip,'\0',sizeof(buf_ip));             inet_ntop(AF_INET,&socket.sin_add,buf_ip,sizeof(buf_ip));        printf("get connect,ip is%s\n",buf_ip);        printf("port=%d\n",ntohs(socket.sin_port));          pthread_create(&thread_id, NULL, (void *)fun, (void *)client_sock);          pthread_detach(thread_id);     }    close(sock);    return 0;}

不管是哪一种的服务器,客户端都是一样的
client.c

#include<stdio.h>#include<unistd.h>#include<sys/socket.h>#include<string.h>#include<errno.h>#include<netinet/in.h>#include<arpa/inet.h>#include<sys/types.h>#define SERVER_PORT 9999int main(int argc,char* argv[]){    if(argc!=2)                                                                                                {           printf("Usage:client IP\n");        return 1;    }       char *str=argv[1];    char buf[1024];    memset(buf,'\0',sizeof(buf));struct sockaddr_in server_sock;    int sock = socket(AF_INET,SOCK_STREAM,0);    bzero(&server_sock,sizeof(server_sock));    server_sock.sin_family=AF_INET;    inet_pton(AF_INET,str,&server_sock.sin_addr);    server_sock.sin_port=htons(SERVER_PORT);    int ret=connect(sock,(struct sockaddr *)&server_sock,sizeof(server_sock));    if(ret<0)    {        printf("connect()\n");        return 1;    }    printf("connect success\n");    while(1)    {        printf("client:# ");        fgets(buf,sizeof(buf),stdin);           buf[strlen(buf)-1]='\0';        write(sock,buf,sizeof(buf));        if(strncasecmp(buf,"quit",4)==0)        {            printf("quit\n");            break;        }        printf("wait..\n");        read(sock,buf,sizeof(buf));        printf("server:$ %s\n",buf);    }    close(sock);    return 0;}
阅读全文
0 0
原创粉丝点击