Linux套接字编程tcp_server

背景知识介绍

socket

socket这个词可以表示很多概念: 在TCP/IP协议中,“IP地址+TCP或UDP端口号”唯一标识网络通讯中的一个进程,“IP地址+端⼜⼝口号”就称为socket。

网络字节序

在两台主机进行通信时如果直接将网络上的数据拿来进行解析如果两台主机之间的字节序不同这样数据就会出错但是又不知道对方主机的字节序,所以就规定了网络字节序为大端

接口介绍

Linux提供了以下函数用来进行主机字节序到网络字节序的转换,或者网络细节序到主机字节序的转换

       #include 
       uint32_t htonl(uint32_t hostlong);
       uint16_t htons(uint16_t hostshort);
       uint32_t ntohl(uint32_t netlong);
       uint16_t ntohs(uint16_t netshort);

其中h代表主机n代表网络
Linux还提供了对IP地址的转换的函数比如将点分十进制到int转换

       #include 
       #include 
       #include 
       int inet_aton(const char *cp, struct in_addr *inp);
       in_addr_t inet_addr(const char *cp);
       in_addr_t inet_network(const char *cp);
       char *inet_ntoa(struct in_addr in);
       struct in_addr inet_makeaddr(int net, int host);
       in_addr_t inet_lnaof(struct in_addr in);
       in_addr_t inet_netof(struct in_addr in);
sockaddr_in(在netinet/in.h中定义):
struct  sockaddr_in {
short  int  sin_family;                      /* Address family */
unsigned  short  int  sin_port;       /* Port number */
struct  in_addr  sin_addr;              /* Internet address */
unsigned  char  sin_zero[8];         /* Same size as struct sockaddr */
};
struct  in_addr {
unsigned  long  s_addr;
};
       #include           /* See NOTES */
       #include 
       int socket(int domain, int type, int protocol);
      socket() creates an endpoint for communication and returns a descriptor.

      int listen(int sockfd, int backlog);//listen的第二个参数是当前在操作系统中排队等待的客户数目
      listen()  marks the socket referred to by sockfd as a passive socket, that is, as a socket that will be used to accept incoming connection requests using accept(2)


       int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);//绑定将socket与ip还有端口绑定
       int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);

编程步骤

Linux套接字编程tcp_server_第1张图片

程序代码

客户端代码

#include 
#include 
#include 
#include 
#include 
#include 
#include 

void usage(const char* arg)
{
    printf("%s [server_ip][server_port]\n",arg);
}

int main(int argc,char* argv[])
{
    if(argc != 3)
    {
        usage(argv[0]);
        return 1;
    }

    int sock=socket(AF_INET,SOCK_STREAM,0);
    if(sock < 0)
    {
        perror("socket:");
        exit(2);
    }

    struct sockaddr_in client;
    client.sin_family = AF_INET;
    client.sin_port = htons(atoi(argv[2]));
    client.sin_addr.s_addr = inet_addr(argv[1]);//这里不用转换为网络字节序

    char buf[1024];
   if(connect(sock,(struct sockaddr*)&client,sizeof(client)) == 0)
    {
        while(1)
        {
            printf("Please Enter:");
            fflush(stdout);
            ssize_t size = read(0,buf,sizeof(buf)-1);
            if(size > 0)
            {
                buf[size]=0;
                write(sock,buf,strlen(buf));
                size = read(sock,buf,sizeof(buf)-1);
                buf[size]=0;
                printf("%s",buf);
            }
            else if(size == 0)
            {
                printf("server quit");
                break;
            }
            else
            {
                perror("read");
                break;
            }
        }
    }
    return 0;
}

服务器单用户模式

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

void usage(const char* arg)
{
    printf("%s[ip][port]\n",arg);
}

int getsock(const char* _ip,const char* _port)
{
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(atoi(_port));
    server.sin_addr.s_addr = inet_addr(_ip);

   if(bind(sock,(struct sockaddr*)&server,sizeof(server)) < 0)
    {
        perror("bind:");
        exit(2);
    }

   if(listen(sock,5)<0)
   {
       perror("listen");
       exit(3);
   }

    return sock;
}

int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        usage(argv[0]);
        return 1;
    }

   int sock=getsock(argv[1],argv[2]);
   while(1)
   {
        struct sockaddr_in server;
        socklen_t len=sizeof(server);
        int new_sock = accept(sock,(struct sockaddr*)&server,&len);
        if(new_sock<0)
        {
             perror("accept:");
             continue;   
        }
        char buf[1024];
        printf("wait client...\n");
        while(1)
        {
            ssize_t size=read(new_sock,buf,sizeof(buf)-1);
            if(size<0)
            {
                close(new_sock);
                perror("read:");
                break;
            }
            else if(size == 0)
            {
                close(new_sock);
                printf("client is quit...\n");
                break;
            }
            else
            {
               buf[size]=0;
               printf("%s",buf);
               write(new_sock,buf,strlen(buf));
            }
        }
   }
   return 0;
}

多进程版本

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

void usage(const char* arg)
{
    printf("%s[ip][port]\n",arg);
}

int getsock(const char* _ip,const char* _port)
{
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(atoi(_port));
    server.sin_addr.s_addr = inet_addr(_ip);

   if(bind(sock,(struct sockaddr*)&server,sizeof(server)) < 0)
    {
        perror("bind:");
        exit(2);
    }

   if(listen(sock,5)<0)
   {
       perror("listen");
       exit(3);
   }

    return sock;
}

int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        usage(argv[0]);
        return 1;
    }

   int sock=getsock(argv[1],argv[2]);
   while(1)
   {
        struct sockaddr_in server;
        socklen_t len=sizeof(server);
        int new_sock = accept(sock,(struct sockaddr*)&server,&len);
        if(new_sock<0)
        {
             perror("accept:");
             continue;   
        }
         pid_t id = fork();
         if(id < 0)
         {
             perror("fork");
             exit(4);
         }
         else if(id == 0)
         {
             pid_t pid=fork(); //再次fork退出父进程子进程变为孤儿进程由init进程回收原父进程不必等待子进程退出回收子进程
             if(pid>0)
             {
                 exit(6);
             }

             char buf[1024];
             printf("wait client...\n");
             while(1)
             {
                 ssize_t size=read(new_sock,buf,sizeof(buf)-1);
                 if(size<0)
                 {
                    close(new_sock);
                    perror("read:");
                    break;
                }
                else if(size == 0)
                {
                 close(new_sock);
                 printf("client is quit...\n");
                 break;
                }
                else
                {
                 buf[size]=0;
                 printf("%s",buf);
                 write(new_sock,buf,strlen(buf));
                }
            }
         }
         else
         {
             close(new_sock);    
         }

    }
    return 0;
}

多线程版本

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 

void usage(const char* arg)
{
    printf("%s[ip][port]\n",arg);
}

int getsock(const char* _ip,const char* _port)
{
    int sock = socket(AF_INET,SOCK_STREAM,0);
    if(sock<0)
    {
        perror("socket");
        exit(1);
    }

    struct sockaddr_in server;
    server.sin_family = AF_INET;
    server.sin_port = htons(atoi(_port));
    server.sin_addr.s_addr = inet_addr(_ip);

   if(bind(sock,(struct sockaddr*)&server,sizeof(server)) < 0)
    {
        perror("bind:");
        exit(2);
    }

   if(listen(sock,5)<0)
   {
       perror("listen");
       exit(3);
   }

    return sock;
}

void* service(void* arg)
{
    char buf[1024];
    int new_sock = (int)arg;
    printf("wait client...\n");
    while (1)
    {
        ssize_t size = read(new_sock, buf, sizeof(buf) - 1);
        if (size < 0)
        {
            close(new_sock);
            perror("read:");
            break;
        }
        else if (size == 0)
        {
            close(new_sock);
            printf("client is quit...\n");
            break;
        }
        else
        {
            buf[size] = 0;
            printf("%s", buf);
            write(new_sock, buf, strlen(buf));
        }
    }
}

int main(int argc,char* argv[])
{
    if(argc!=3)
    {
        usage(argv[0]);
        return 1;
    }

   int sock=getsock(argv[1],argv[2]);
   while(1)
   {
        struct sockaddr_in server;
        socklen_t len=sizeof(server);
        int new_sock = accept(sock,(struct sockaddr*)&server,&len);
        if(new_sock<0)
        {
             perror("accept:");
             continue;   
        }
        pthread_t id;
        pthread_create(&id,NULL,service,(void*)new_sock);
        pthread_detach(id);//设置为线程分离不必回收线程退出状态
   }
   return 0;
}

你可能感兴趣的:(linux网络编程)