树莓派3B--通过TCP远程控制GPIO(C++)

一、分析

1、GPIO口初始化借助wiringPi;

2、利用linux下socket中的API,进行TCP通信

 

二、一个服务端和一个客户端

1、server端

//
/************************************************************************* 
    > File Name: server.c 
    > Author: Sen 
    > Date: 2018-5-8 
 ************************************************************************/  
  
#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <arpa/inet.h>  
#include <netinet/in.h> 
#include <wiringPi.h>
#include <wiringSerial.h> 
  
const int port = 8888;  
const char* ip = "192.168.1.88";   
  
int main()  
{  
      //创建套接字,即创建socket   
      int ser_sock = socket(AF_INET, SOCK_STREAM, 0);   
      if(ser_sock < 0)  
      {  
          //创建失败  
          perror("socket");  
          return 1;  
      }  
  
      //绑定信息,即命名socket   
      struct sockaddr_in addr;   
      addr.sin_family = AF_INET;   
      addr.sin_port = htons(port);   
      //inet_addr函数将用点分十进制字符串表示的IPv4地址转化为用网络   
      //字节序整数表示的IPv4地址   
      addr.sin_addr.s_addr = inet_addr(ip);   
      if(bind(ser_sock, (struct sockaddr*)&addr, sizeof(addr)) < 0)   
      {               
           //命名失败   
           perror("bind");   
           return 2;         
      }   
  
      //监听socket  
      int listen_sock = listen(ser_sock, 5);  
      if(listen_sock < 0)  
      {  
          //监听失败  
          perror("listen");  
          return 3;  
      }  
  
      //接受连接  
      //系统调用从listen监听队列中接受一个连接  
      //int accept(int sockfd, struct sockaddr* addr, socklen_t* addrlen)  
      //sockfd参数是执行过listen系统调用的监听socket;addr参数用来获取被  
      //接受连接的远端socket地址,该socket地址的长度由addrlen参数指出  
      //accept成功时返回一个新的连接socket,该socket唯一的标识了被接受  
      //的这个连接,服务器可通过读写该socket来与被接受连接对应的客户端通信  
      struct sockaddr_in peer;  
      socklen_t peer_len;  
      char buf[1024];  
      int accept_fd = accept(ser_sock, (struct sockaddr*)&peer, &peer_len);  
  
      if(accept_fd < 0)  
      {  
          perror("accept");  
          return 4;  
      }  
      else  
      {  
          printf("connected with ip: %s  and port: %d\n", inet_ntop(AF_INET,&peer.sin_addr, buf, 1024), ntohs(peer.sin_port));  
          
      }  
      wiringPiSetup();
      pinMode(0, OUTPUT);
      while(1)  
      {  
          memset(buf, '\0', sizeof(buf));  
          ssize_t size = read(accept_fd, buf, sizeof(buf) - 1);  
          if (size > 0)  
          {  
              printf("client#: %s\n", buf);
	      if (size = 1)
              {   
                  //control GPIO.0
                  int tmp = atoi(buf);
                  if (tmp == 1)
	          {
                      digitalWrite(0, HIGH);
                  } else {
                      digitalWrite(0, LOW);
                  }
              }  
          }
          else if(size == 0)  
          { 
              digitalWrite(0, LOW); 
              printf("read is done...\n");  
              //break;  
          }  
          else   
          {  
              digitalWrite(0, LOW);
              perror("read");  
              //break;  
          }  
      }  
        close(ser_sock);  
      return 0;  
}  
//

2、client端

//
/************************************************************************* 
    > File Name: client.c 
    > Author: Sen  
    > Date: 2018-5-8 
 ************************************************************************/  
  
#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <arpa/inet.h>  
#include <netinet/in.h>  
  
const int port = 8888;  
const char* ip = "192.168.1.88";   
  
int main()  
{  
      //创建套接字,即创建socket   
      int clt_sock = socket(AF_INET, SOCK_STREAM, 0);   
      if(clt_sock < 0)  
      {  
          //创建失败  
          perror("socket");  
          return 1;  
      }  
  
      //绑定信息,即命名socket   
      struct sockaddr_in addr;   
      addr.sin_family = AF_INET;   
      addr.sin_port = htons(port);   
      //inet_addr函数将用点分十进制字符串表示的IPv4地址转化为用网络   
      //字节序整数表示的IPv4地址   
      addr.sin_addr.s_addr = inet_addr(ip);   
  
      //不需要监听  
  
      //发起连接  
//    struct sockaddr_in peer;  
      socklen_t addr_len = sizeof(addr);  
      int connect_fd = connect(clt_sock, (struct sockaddr*)&addr, addr_len);  
      if(connect_fd < 0)  
      {  
          perror("connect");  
          return 2;  
      }  
      char buf[1024];  
  
      while(1)  
      {  
          memset(buf, '\0', sizeof(buf));  
          printf("client please enter: ");  
          fflush(stdout);  
          ssize_t size = read(0, buf, sizeof(buf) - 1);  
          if(size > 0)  
          {  
              buf[size - 1] = '\0';  
          }  
          else if(size == 0)  
          {  
              printf("read is done...\n");  
              break;  
          }  
          else  
          {  
              perror("read");  
              return 4;  
          }  
          write(clt_sock, buf, strlen(buf));  
       }  
      close(clt_sock);  
      return 0;  
}  
//

 

三、一个服务端和多个客户端

1、server端

//
#include <sys/types.h>  
#include <sys/socket.h>  
#include <stdio.h>  
#include <netinet/in.h>  
#include <arpa/inet.h>  
#include <unistd.h>  
#include <string.h>  
#include <stdlib.h>  
#include <fcntl.h>  
#include <sys/shm.h> 
#include <wiringPi.h>
#include <wiringSerial.h> 
  
#define PORT  7654  
#define QUEUE_SIZE   10  
#define BUFFER_SIZE 1024  
  
//传进来的sockfd,就是互相建立好连接之后的socket文件描述符  
//通过这个sockfd,可以完成 [服务端]<--->[客户端] 互相收发数据  
void str_echo(int sockfd)  
{  
    char buffer[BUFFER_SIZE];  
    pid_t pid = getpid();  
    while(1)  
    {  
        memset(buffer,0,sizeof(buffer));  
        int len = recv(sockfd, buffer, sizeof(buffer),0);
        if(strcmp(buffer,"exit\n")==0)  
        {  
            printf("child process: %d exited.\n",pid);  
            break;  
        }
        
        if (len > 0)
        {
            printf("client#: %s\n", buffer);
            if (len = 1 && buffer[0] == '1')
            {
                digitalWrite(0, HIGH);
            } else {
                digitalWrite(0, LOW);
            }
        } else if (len == 0) {
            digitalWrite(0, LOW);
            printf("read is done...\n");
        } else {
            digitalWrite(0, LOW);
            perror("read");
        }

          
        printf("pid:%d receive:\n",pid);  
        //fputs(buffer, stdout);  
        send(sockfd, buffer, len, 0);  
    }  
    close(sockfd);  
}  
  
int main(int argc, char **argv)  
{  
    //GPIO
    wiringPiSetup();
    pinMode(0, OUTPUT);

    //定义IPV4的TCP连接的套接字描述符  
    int server_sockfd = socket(AF_INET,SOCK_STREAM, 0);  
  
    //定义sockaddr_in  
    struct sockaddr_in server_sockaddr;  
    server_sockaddr.sin_family = AF_INET;  
    server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);  
    server_sockaddr.sin_port = htons(PORT);  
  
    //bind成功返回0,出错返回-1  
    if(bind(server_sockfd,(struct sockaddr *)&server_sockaddr,sizeof(server_sockaddr))==-1)  
    {  
        perror("bind");  
        exit(1);//1为异常退出  
    }  
    printf("bind success.\n");  
  
    //listen成功返回0,出错返回-1,允许同时帧听的连接数为QUEUE_SIZE  
    if(listen(server_sockfd,QUEUE_SIZE) == -1)  
    {  
        perror("listen");  
        exit(1);  
    }  
    printf("listen success.\n");  
  
    for(;;)  
    {  
        struct sockaddr_in client_addr;  
        socklen_t length = sizeof(client_addr);  
        //进程阻塞在accept上,成功返回非负描述字,出错返回-1  
        int conn = accept(server_sockfd, (struct sockaddr*)&client_addr,&length);  
        if(conn<0)  
        {  
            perror("connect");  
            exit(1);  
        }  
        printf("new client accepted.\n");  
  
        pid_t childid;  
        if(childid=fork()==0)//子进程  
        {  
            printf("child process: %d created.\n", getpid());  
            close(server_sockfd);//在子进程中关闭监听  
            str_echo(conn);//处理监听的连接  
            exit(0);  
        }  
    }  
  
    printf("closed.\n");  
    close(server_sockfd);  
    return 0;  
}  
//

2、client端

//
/************************************************************************* 
    > File Name: client.c 
    > Author: Sen  
    > Date: 2018-5-8 
 ************************************************************************/  
  
#include <stdio.h>  
#include <string.h>  
#include <stdlib.h>  
#include <sys/types.h>  
#include <sys/socket.h>  
#include <sys/un.h>  
#include <arpa/inet.h>  
#include <netinet/in.h>  
  
const int port = 7654;  
const char* ip = "192.168.1.32";   
  
int main()  
{  
      //创建套接字,即创建socket   
      int clt_sock = socket(AF_INET, SOCK_STREAM, 0);   
      if(clt_sock < 0)  
      {  
          //创建失败  
          perror("socket");  
          return 1;  
      }  
  
      //绑定信息,即命名socket   
      struct sockaddr_in addr;   
      addr.sin_family = AF_INET;   
      addr.sin_port = htons(port);   
      //inet_addr函数将用点分十进制字符串表示的IPv4地址转化为用网络   
      //字节序整数表示的IPv4地址   
      addr.sin_addr.s_addr = inet_addr(ip);   
  
      //不需要监听  
  
      //发起连接  
//    struct sockaddr_in peer;  
      socklen_t addr_len = sizeof(addr);  
      int connect_fd = connect(clt_sock, (struct sockaddr*)&addr, addr_len);  
      if(connect_fd < 0)  
      {  
          perror("connect");  
          return 2;  
      }  
      char buf[1024];  
  
      while(1)  
      {  
          memset(buf, '\0', sizeof(buf));  
          printf("client please enter: ");  
          fflush(stdout);  
          ssize_t size = read(0, buf, sizeof(buf) - 1);  
          if(size > 0)  
          {  
              buf[size - 1] = '\0';  
          }  
          else if(size == 0)  
          {  
              printf("read is done...\n");  
              break;  
          }  
          else  
          {  
              perror("read");  
              return 4;  
          }  
          write(clt_sock, buf, strlen(buf));  
       }  
      close(clt_sock);  
      return 0;  
}  
//

 

 

 

 

 

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

worthsen

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值