Socket編程,分別作為服務器和客戶端的簡單通信實現


  進程間的通信有很多種方法,本地進程之間通過一個唯一標識的pid進行通信,網絡之間的進程進行通信,也需要一個唯一的標志符。根據TCP/IP協議,網絡層的ip地址可以唯一的標識網絡中的一台主機,協議加端口號可以標識這台主機中的進程。ip地址,協議加端口就可以唯一標識網絡中的進程,進程之間可以通過這個標識進行通信。

  目前幾乎所有網絡進程都是采用socket進行通信。socket起源於Unix,而Unix/Linux基本哲學之一就是“一切皆文件”,都可以用“打開open –> 讀寫write/read –> 關閉close”模式來操作。我的理解就是Socket就是該模式的一個實現,socket即是一種特殊的文件,一些socket函數就是對其進行的操作(讀/寫IO、打開、關閉),這些函數在很多文章里都有介紹,這里不再贅述。

  socket通信中,一個進程需要被設置成服務器,另一個需要被設置成客戶端。我們將第一個進程分別設置成服務器和客戶端,另一個進程我們在電腦中安裝網絡調試助手,設置成對應的客戶端和服務器,測試它們之間的通信情況。

  設置成服務器的代碼如下:

#define BUFF_LEN    ( 512 )

static int thread_step = 0;
static int socket_server_fd = 0;
static int conn_fd = 0;
 
void socket_server_mode(void)
{
   print_ids("socket rcv thread:");
   struct sockaddr_in socketaddr;
   unsigned char buf[BUFF_LEN] = {0};
   ssize_t recv_len;

   int ret = -1;
   while(1)
   {
      printf("thread step = %d \n",thread_step);
      switch(thread_step)
      {   
         case 0://socket
            printf("socket case 0\n");
            socket_server_fd = socket(AF_INET, SOCK_STREAM, 0);
            if(-1 == socket_server_fd)
            {
               perror("socket\n");
               sleep(1);
               break;
            }
            printf("creat socket success\n");
            thread_step = 1;
            break;
 
         case 1:
            printf("socket case 1\n");
            memset(&socketaddr, 0, sizeof(socketaddr));
            socketaddr.sin_family    = AF_INET;
            socketaddr.sin_port     = htons(8080);
            socketaddr.sin_addr.s_addr = htonl(INADDR_ANY);
            if(bind(socket_server_fd, (struct sockaddr*)&socketaddr, sizeof(socketaddr))  == -1)
            {
               sleep(1);
               break;
            }
            thread_step = 2;
         break;
 
         case 2:
            printf("socket case 2\n");
            ret = listen(socket_server_fd, 10);
            printf("listen return value is %d\n",ret);
            if(ret == -1)
            {
               sleep(1);
               break;
            }
            else
            {
               thread_step = 3;
            }
        break;
   
          case 3:
           printf("socket case 3\n");
             if((conn_fd = accept(socket_server_fd, (struct sockaddr*)NULL, NULL)) == -1)
                  {
                      printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
                      continue;
                }
             thread_step = 4;
         break;
  
         case 4:
            printf("socket case 4\n");
                 recv_len = recv(conn_fd, buf, sizeof(buf),0);
            printf("rcv len = %d \n",recv_len);
                 buf[recv_len] = '\0';
                 if(recv_len)
            {
               printf("rcv info is = %s \n",buf);
               memset(buf, 0, strlen(buf));
            }
         break;  
      
        default:
    
         break;
       }
   }
   return ((void*)0);
}

 

設置成客戶端的代碼如下:

#define SERVER_ADDR   ( "192.168.0.132" )
#define SERVER_IP     ( 8080 )

static int thread_step = 0;
static int socket_fd = 0;
void socket_client_mode(void)
{
   print_ids("socket rcv thread:");
   int ret = -1;
   unsigned char buf[BUFF_LEN] = {0};
   struct sockaddr_in socketaddr;
   ssize_t recv_len;
   while(1)
   {
      printf("thread step = %d \n",thread_step);
      switch(thread_step)
      {
         case 0://socket
            printf("socket case 0\n");
            socket_fd = socket(AF_INET, SOCK_STREAM, 0);
            if(-1 == socket_fd)
            {
               perror("socket\n");
               sleep(1);
               break;
            }
            printf("creat socket success\n");
            thread_step = 1;
          break;
 
         case 1://connect
            printf("socket case 1\n");
            memset(&socketaddr, 0, sizeof(socketaddr));
            socketaddr.sin_family    = AF_INET;
            socketaddr.sin_port     = htons(SERVER_IP);
            socketaddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
            if(connect(socket_fd, (struct sockaddr*)&socketaddr, sizeof(socketaddr)) == -1)
            {
               perror("connect \n");
               //close(socket_fd);
               sleep(1);
               break;
            }
            thread_step = 2;
         break;
   
         case 2://revc
          {
             printf("socket case 2\n");
             recv_len = recv(socket_fd, buf, sizeof(buf), 0);
             printf("rcv len = %d\n",recv_len);
             if(recv_len)
             {
                printf("rcv info is = %s \n",buf);
                memset(buf, 0, strlen(buf));
             } 
          }  
         break;
 
         default:
    
         break;
      }
   }
   return ((void*)0);
}

發送數據的代碼如下:

static int socket_mode = 0;

static char socket_send[100] = {0};

void socket_send_data(const char* data)
{
   int len = strlen(data);
   strcpy(socket_send,data);
   if(socket_mode)
   {
      if(send(socket_fd, socket_send, strlen(socket_send), 0) < 0)
      {
         printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
         exit(0);
      }
   }
   else if(thread_step == 4)
   { 
      if(send(conn_fd, socket_send, strlen(socket_send), 0) < 0)
      {
         printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
         //exit(0);
      }
   }
   else
   {}
}

void test_send_data(void)

{

   static int data = 0;

   char string1[30];

   while(1)

   {

     if(data<100)

     {

       data++;

     }
        sprintf(string1,"%d",data);
        puts(string1);
        char* str1 ="socket send data:";
        char* str2 =(char *) malloc(strlen(str1) + strlen(string1)+1);
        strcpy(str2, str1);
        strcat(str2, string1);
        socket_send_data(str2);
        printf("send info is : %s\n",str2);
        free(str2);
        str2 = NULL;

     sleep(1);

   }

}

 

完整代碼如下:


#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <pthread.h>

#define BUFF_LEN    ( 512 )
#define SERVER_ADDR   ( "192.168.0.132" )
#define SERVER_IP     ( 8080 )

static int thread_step = 0;
static int socket_fd = 0;
static int socket_server_fd = 0;
static char socket_send[100] = {0};
static int socket_mode = 0;
static int conn_fd = 0;
void socket_send_data(const char* data)
{
   int len = strlen(data);
   strcpy(socket_send,data);
   if(socket_mode)
   {
      if(send(socket_fd, socket_send, strlen(socket_send), 0) < 0)
      {
         printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
         exit(0);
      }
   }
   else if(thread_step == 4)
   { 
      if(send(conn_fd, socket_send, strlen(socket_send), 0) < 0)
      {
         printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
         //exit(0);
      }
   }
   else
   {}
}
 
void* send_thread_fun(void *arg)

{

   static int data = 0;

   char string1[30];

   while(1)

   {

     if(data<100)

     {

       data++;

     }
        sprintf(string1,"%d",data);
        puts(string1);
        char* str1 ="socket send data:";
        char* str2 =(char *) malloc(strlen(str1) + strlen(string1)+1);
        strcpy(str2, str1);
        strcat(str2, string1);
        socket_send_data(str2);
        printf("send info is : %s\n",str2);
        free(str2);
        str2 = NULL;
          sleep(1);

   }

}

 

void socket_server_mode(void)
{
   print_ids("socket rcv thread:");
   struct sockaddr_in socketaddr;
   unsigned char buf[BUFF_LEN] = {0};
   ssize_t recv_len;

   int ret = -1;
   while(1)
   {
      printf("thread step = %d \n",thread_step);
      switch(thread_step)
      {   
         case 0://socket
            printf("socket case 0\n");
            socket_server_fd = socket(AF_INET, SOCK_STREAM, 0);
            if(-1 == socket_server_fd)
            {
               perror("socket\n");
               sleep(1);
               break;
            }
            printf("creat socket success\n");
            thread_step = 1;
            break;
 
         case 1:
            printf("socket case 1\n");
            memset(&socketaddr, 0, sizeof(socketaddr));
            socketaddr.sin_family    = AF_INET;
            socketaddr.sin_port     = htons(8080);
            socketaddr.sin_addr.s_addr = htonl(INADDR_ANY);
            if(bind(socket_server_fd, (struct sockaddr*)&socketaddr, sizeof(socketaddr))  == -1)
            {
               sleep(1);
               break;
            }
            thread_step = 2;
         break;
 
         case 2:
            printf("socket case 2\n");
            ret = listen(socket_server_fd, 10);
            printf("listen return value is %d\n",ret);
            if(ret == -1)
            {
               sleep(1);
               break;
            }
            else
            {
               thread_step = 3;
            }
        break;
   
          case 3:
           printf("socket case 3\n");
             if((conn_fd = accept(socket_server_fd, (struct sockaddr*)NULL, NULL)) == -1)
                  {
                      printf("accept socket error: %s(errno: %d)",strerror(errno),errno);
                      continue;
                }
             thread_step = 4;
         break;
  
         case 4:
            printf("socket case 4\n");
                 recv_len = recv(conn_fd, buf, sizeof(buf),0);
            printf("rcv len = %d \n",recv_len);
                 buf[recv_len] = '\0';
                 if(recv_len)
            {
               printf("rcv info is = %s \n",buf);
               memset(buf, 0, strlen(buf));
            }
         break;  
      
        default:
    
         break;
       }
   }
   return ((void*)0);
}
 
void socket_client_mode(void)
{
   print_ids("socket rcv thread:");
   int ret = -1;
   unsigned char buf[BUFF_LEN] = {0};
   struct sockaddr_in socketaddr;
   ssize_t recv_len;
   while(1)
   {
      printf("thread step = %d \n",thread_step);
      switch(thread_step)
      {
         case 0://socket
            printf("socket case 0\n");
            socket_fd = socket(AF_INET, SOCK_STREAM, 0);
            if(-1 == socket_fd)
            {
               perror("socket\n");
               sleep(1);
               break;
            }
            printf("creat socket success\n");
            thread_step = 1;
          break;
 
         case 1://connect
            printf("socket case 1\n");
            memset(&socketaddr, 0, sizeof(socketaddr));
            socketaddr.sin_family    = AF_INET;
            socketaddr.sin_port     = htons(SERVER_IP);
            socketaddr.sin_addr.s_addr = inet_addr(SERVER_ADDR);
            if(connect(socket_fd, (struct sockaddr*)&socketaddr, sizeof(socketaddr)) == -1)
            {
               perror("connect \n");
               //close(socket_fd);
               sleep(1);
               break;
            }
            thread_step = 2;
         break;
   
         case 2://revc
          {
             printf("socket case 2\n");
             recv_len = recv(socket_fd, buf, sizeof(buf), 0);
             printf("rcv len = %d\n",recv_len);
             if(recv_len)
             {
                printf("rcv info is = %s \n",buf);
                memset(buf, 0, strlen(buf));
             } 
          }  
         break;
 
         default:
    
         break;
      }
   }
   return ((void*)0);
}

void* socket_thread_fun(void *arg)
{
   if(socket_mode)
   {
      socket_client_mode();
   }
   else
   {
      socket_server_mode();
   }
}  

int main(int argc, char **argv)
{
   int ret = -1;

   pthread_t send_thread;
   pthread_t socket_thread;
 
   pthread_create(&send_thread, NULL, send_thread_fun, NULL);
   pthread_create(&socket_thread, NULL, socket_thread_fun, NULL);
 
   pthread_join(send_thread,NULL);
   pthread_join(socket_thread,NULL);
   return 0;
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM