• socket编程与利用进程进行多并行连接


           呈现一张基本的socket阻塞式模型,如下图:

                        

     一: 对于一对一的进行C/S回射:

    服务端(server.c):

     1 #include<unistd.h>
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<stdlib.h>
     5 #include<netinet/in.h>
     6 #include<sys/socket.h>
     7 #include<sys/types.h>
     8 #include<error.h>
     9 
    10 #define ERR_EXIT(m) 
    11    do{           
    12       perror(m); 
    13       exit(1);    
    14      }while(0)
    15 
    16 int
    17 main (void)
    18 {
    19   int sock, conn;
    20   if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0)
    21     ERR_EXIT ("socket");
    22   struct sockaddr_in sockaddr;
    23   memset (&sockaddr, 0, sizeof (sockaddr));
    24   sockaddr.sin_family = AF_INET;
    25   sockaddr.sin_port = htons (5528);
    26   sockaddr.sin_addr.s_addr = htonl (INADDR_ANY);
    27   if (bind (sock, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0)
    28     ERR_EXIT ("Bind");
    29   if (listen (sock, SOMAXCONN) < 0)
    30     ERR_EXIT ("Listen");
    31   struct sockaddr_in client;
    32   memset (&client, 0, sizeof (client));
    33   socklen_t addrlen = sizeof (client);
    34   if ((conn = accept (sock, (struct sockaddr *) &client, &addrlen)) < 0)
    35     ERR_EXIT ("Accept");
    36   char sed[1024], recv[1024];
    37   while (fgets (sed, sizeof (sed), stdin) != NULL || 1 == 1)
    38     {
    39       if (strlen (sed) > 0)
    40         write (conn, sed, sizeof (sed));
    41       if (read (conn, recv, sizeof (recv)) > 0)
    42         {
    43           fputs (recv, stdout);
    44           if (strcmp (recv, "exit") == 0)
    45             break;
    46           write (conn, recv, sizeof (recv));
    47         }
    48       else
    49         ERR_EXIT ("read...");
    50     }
    51   close (conn);
    52   close (sock);
    53   return 0;
    54 }

    客户端(client.c):

       

     1 #include<unistd.h>
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<error.h>
     5 #include<netinet/in.h>
     6 #include<stdlib.h>
     7 #include<sys/socket.h>
     8 #include<sys/types.h>
     9                                                                                
    10 #define ERR_EXIT( m ) 
    11    do{          
    12       perror(m);   
    13       exit(1);       
    14     }while(0);
    15                                                                                
    16 int
    17 main (void)
    18 {
    19   int socketid, conn;
    20                                                                                
    21   if ((socketid = socket (PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
    22     ERR_EXIT ("socket");
    23 
    24   struct sockaddr_in server_addr;
    25   memset (&server_addr, 0, sizeof (server_addr));
    26 
    27   server_addr.sin_family = AF_INET;
    28   server_addr.sin_port = htons (5528);
    29   server_addr.sin_addr.s_addr = inet_addr ("127.0.0.1");
    30   if ((conn =
    31        connect (socketid, (struct sockaddr *) &server_addr,
    32                 sizeof (server_addr))) < 0)
    33     ERR_EXIT ("connect");
    34   char sendbuf[1024], recivebuf[1024];
    35   while (fgets (sendbuf, sizeof (sendbuf), stdin) != NULL)
    36     {
    37       write (socketid, sendbuf, sizeof (sendbuf));
    38       read (socketid, recivebuf, sizeof (recivebuf));
    39       fputs (recivebuf, stdout);
    40       if (strcmp (recivebuf, "exit") == 0)
    41         {
    42           ERR_EXIT ("exit");
    43           break;
    44         }
    45     }
    46   close (conn);
    47   close (socketid);
    48   return 0;
    49 }

      相关的makefile文件

       

     1 makefile文件:
     2 
     3 .SUFFIXES: .o.c
     4 .PHONY: clean
     5 .PHONY: start
     6 
     7 CC =gcc
     8 SRC =server.c
     9 OBJS =$(SRC:.c =.o)
    10 BIN = Server
    11 
    12 start:
    13         $(CC) -o $(BIN) $(OBJS)
    14 
    15 .o.c:
    16         $(CC) -g -Wall $@ -c $<
    17 clean:
    18         rm -f $(OBJS)

    但是上述虽然满足了基本的socket套路,但是当我们关闭服务可执行程序时,在开启就会出现地址被占用,解决此等问题,需再加上一个setsockopt()函数,对齐进行设定。

    详细可以去查询man帮助(man  setsockopt)

       代码:
             

    1  int on = 1;
    2   if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
    3     {
    4       ERR_EXIT ("setsockopt");
    5     }
    6 
    7 
    8   if (bind (sock, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0)
    9     ERR_EXIT ("Bind");

      二:  利用进程进行并行socket阻塞式连接:

            客户端和makefile文件和上面一样,只是将socket的服务端,修改为调用进程来进行多并发连接即可!

          服务端(server.c):

      

     1 #include<unistd.h>
     2 #include<stdio.h>
     3 #include<string.h>
     4 #include<stdlib.h>
     5 #include<netinet/in.h>
     6 #include<sys/socket.h>
     7 #include<sys/types.h>
     8 #include<error.h>
     9 
    10 #define ERR_EXIT(m) 
    11    do{           
    12       perror(m); 
    13       exit(1);    
    14      }while(0)
    15 
    16 
    17 void
    18 print (int conn){
    19 
    20   char sed[1024], recv[1024];
    21   while (fgets (sed, sizeof (sed), stdin) != NULL || 1 == 1)
    22     {
    23       if (strlen (sed) > 0)
    24          write (conn, sed, sizeof (sed));
    25       if (read (conn, recv, sizeof (recv)) > 0)
    26         {
    27           fputs (recv, stdout);
    28           if (strcmp (recv, "exit") == 0)
    29                     break;
    30           write (conn, recv, sizeof (recv));
    31         }
    32       else
    33         ERR_EXIT ("read...");
    34    }
    35     close (conn);
    36 }
    37 
    38 int
    39 main (void)
    40 {
    41   int sock, conn;
    42   if ((sock = socket (PF_INET, SOCK_STREAM, 0)) < 0)
    43     ERR_EXIT ("socket");
    44   struct sockaddr_in sockaddr;
    45   memset (&sockaddr, 0, sizeof (sockaddr));
    46   sockaddr.sin_family = AF_INET;
    47   sockaddr.sin_port = htons (5528);
    48   sockaddr.sin_addr.s_addr = htonl (INADDR_ANY);
    49 
    50   int on = 1;
    51   if (setsockopt (sock, SOL_SOCKET, SO_REUSEADDR, &on, sizeof (on)) < 0)
    52     {
    53       ERR_EXIT ("setsockopt");
    54     }
    55 
    56 
    57   if (bind (sock, (struct sockaddr *) &sockaddr, sizeof (sockaddr)) < 0)
    58     ERR_EXIT ("Bind");
    59 
    60   if (listen (sock, SOMAXCONN) < 0)
    61     ERR_EXIT ("Listen");
    62 
    63   struct sockaddr_in client;
    64   memset (&client, 0, sizeof (client));
    65   socklen_t addrlen = sizeof (client);
    66   pid_t pid ;
    67 
    68   while (1)
    69     {
    70    if((conn = accept (sock, (struct sockaddr *) &client, &addrlen)) < 0)
    71         ERR_EXIT ("Accept");
    72           pid = fork ();
    73       if (pid == -1)
    74            ERR_EXIT ("fork");
    75       else if (pid == 0){
    76            close (sock);
    77            print (conn);
    78         }
    79       else
    80         close (conn);
    81     }
    82   close (sock);
    83   return 0;
    84 }

        

  • 相关阅读:
    Postgres 的 Range 类型
    Postgres 的 Array 类型
    joi库 学习笔记
    nginx官方文档 之 http负载均衡 学习笔记
    pm2 官方文档 学习笔记
    SSH 学习笔记
    防止活动上线时 微信openid 被伪造的解决办法
    PHP 中 var_export、print_r、var_dump 调试中的区别
    nake_api_protect 请求保护器——防止请求被恶意刷
    接口的防刷办法
  • 原文地址:https://www.cnblogs.com/gongxijun/p/4592864.html
Copyright © 2020-2023  润新知