树莓派和上位机使用TCP通信(字符串和图像传输)

9 篇文章 3 订阅

树莓派和上位机使用TCP通信

系统介绍

下位机: 树莓派作为下位机,IP地址为192.168.199.206,作为tcp的客户端(c实现),通信端口号为8888,
上位机: Ubuntu(虚拟机)作为上位机,作为tcp的服务端(Qt实现),Qt版本为5.12,IP地址为192.168.199.149,通信端口为8888

注意:

  • 该系统为单向通信,只能由客户端发送到服务端,发信数据类型为字符串或图像数据
  • 此项目需要在Qt设计师中添加一个Label控件,用于显示文本和图像

字符串通信

树莓派具体实现代码:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>

int main(int argc,char *argv[])
{
    int sockfd,numbytes;
    char buf[BUFSIZ];
    struct sockaddr_in their_addr;
    while((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1);
    printf("We get the sockfd~\n");
    their_addr.sin_family = AF_INET;
    their_addr.sin_port = htons(8888);
    their_addr.sin_addr.s_addr=inet_addr("192.168.199.149");
    bzero(&(their_addr.sin_zero), 8);			//清空数据中前8位
    
    while(connect(sockfd,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)) == -1);
    printf("Get the Server~Cheers!\n");
    buf[numbytes]='\0';  
    while(1)
    {
        printf("Entersome thing:");
        scanf("%s",buf);
        numbytes = send(sockfd, buf, strlen(buf), 0);
    }
    close(sockfd);
    return 0;
}

Qt具体实现代码:

Qt如果需要使用socket通信,需要在pro文件中添加以下语句:

QT       += network

头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QDebug>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    QTcpServer *tcpServer = new QTcpServer();   //Tcp服务端对象
    QTcpSocket *tcpSocket = new QTcpSocket();   //Tcp连接socket

    void initWindow();                          //初始化窗体
    void setNetwork();                          //设置网络信息

private slots:
    void serverNewConnect();                    //新的网络连接响应
    void serverReadData();                      //服务端读取数据
    void serverDisconnection();                 //服务端断开连接
};

#endif // MAINWINDOW_H

实现文件

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initWindow();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initWindow()
{
    //初始化窗体
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(serverNewConnect()));
    setNetwork();
}

void MainWindow::setNetwork()
{
    //开启网络服务
    int port = 8888;                //Tcp端口号为8888
    if(!tcpServer->listen(QHostAddress::Any, port))
    {
        qDebug() << "服务器端监听失败!!!";
        return;
    }else
    {
        qDebug() << "服务器端监听成功!!!";
    }
}

void MainWindow::serverNewConnect()
{
    //服务端新连接槽函数
    tcpSocket = tcpServer->nextPendingConnection();
    if(!tcpSocket)
    {
        qDebug() << "未能成功获取客户端连接!!!";
    }else
    {
        qDebug() << "成功建立连接!!!";
        connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(serverReadData()));
        connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(serverDisconnection()));
    }
}

void MainWindow::serverReadData()
{
    //服务器接收数据函数
    ui->label->setText((QString)tcpSocket->readAll());
}

void MainWindow::serverDisconnection()
{
    //服务端断开连接
    qDebug() << "与客户端断开连接!!!";
    return;
}

程序执行

  • 打开上位机中Qt程序,使得服务器监测客户端的连接
  • 执行客户端,可以看到服务端输出连接成功提示语句
  • 在客户端中输入字符,以回车结束,服务端即可打印出相应字符

程序执行效果如下:
在这里插入图片描述

图像发送

树莓派具体实现代码:

#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define MAXSIZE 1024*1024

int main(int argc,char *argv[])
{
    int sockfd,len;
    char buffer[MAXSIZE];
    struct sockaddr_in their_addr;
    FILE *fq;

    while((sockfd = socket(AF_INET,SOCK_STREAM,0)) == -1);

    printf("We get the sockfd~\n");
    their_addr.sin_family = AF_INET;
    their_addr.sin_port = htons(8888);
    their_addr.sin_addr.s_addr=inet_addr("192.168.199.149");
    bzero(&(their_addr.sin_zero), 8);
    
    while(connect(sockfd,(struct sockaddr*)&their_addr,sizeof(struct sockaddr)) == -1);
      
    //需要确保当前目录下有相应图像文件
    if((fq = fopen("./luo.jpg","rb") ) == NULL ){
        printf("File open.\n");
        close(sockfd);
        exit(1);
    }

    while(!feof(fq)){
        len = fread(buffer, 1, sizeof(buffer), fq);
        printf("len is : %d\n", len);
        if(len != write(sockfd, buffer, len)){
            break;
        }
    }
    
    close(sockfd);
    fclose(fq);
    return 0;
}

Qt具体实现代码:

Qt如果需要使用socket通信,需要在pro文件中添加以下语句:

QT       += network

头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QBuffer>
#include <QDebug>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();

private:
    Ui::MainWindow *ui;

    QByteArray array;                           //图像文件
    QTcpServer *tcpServer = new QTcpServer();   //Tcp服务端对象
    QTcpSocket *tcpSocket = new QTcpSocket();   //Tcp连接socket

    void initWindow();                          //初始化窗体
    void setNetwork();                          //设置网络信息

private slots:
    void serverNewConnect();                    //新的网络连接响应
    void serverReadData();                      //服务端读取数据
    void serverDisconnection();                 //服务端断开连接
};

#endif // MAINWINDOW_H

实现文件

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    initWindow();
}

MainWindow::~MainWindow()
{
    delete ui;
}

void MainWindow::initWindow()
{
    //初始化窗体
    connect(tcpServer, SIGNAL(newConnection()), this, SLOT(serverNewConnect()));
    setNetwork();
}

void MainWindow::setNetwork()
{
    //开启网络服务
    int port = 8888;                //Tcp端口号为8888
    if(!tcpServer->listen(QHostAddress::Any, port))
    {
        qDebug() << "服务器端监听失败!!!";
        return;
    }else
    {
        qDebug() << "服务器端监听成功!!!";
    }
}

void MainWindow::serverNewConnect()
{
    //服务端新连接槽函数
    tcpSocket = tcpServer->nextPendingConnection();
    if(!tcpSocket)
    {
        qDebug() << "未能成功获取客户端连接!!!";
    }else
    {
        qDebug() << "成功建立连接!!!";
        connect(tcpSocket, SIGNAL(readyRead()), this, SLOT(serverReadData()));
        connect(tcpSocket, SIGNAL(disconnected()), this, SLOT(serverDisconnection()));
    }
}

void MainWindow::serverReadData()
{
    //服务器接收数据函数
    array.append((QByteArray)tcpSocket->readAll());
}

void MainWindow::serverDisconnection()
{
    //服务端断开连接
    qDebug() << "与客户端断开连接!!!";

    QBuffer buffer(&array);
    buffer.open(QIODevice::ReadOnly);
    QPixmap picture;
    picture.loadFromData(array, "jpg");
    ui->label->setPixmap(picture);

    return;
}

程序执行

  • 打开上位机中Qt程序,使得服务器监测客户端的连接
  • 执行客户端,可以看到服务端输出连接成功提示语句(首先需要确保在客户端路径下有相应图像文件)
  • 在客户端会输出图像文件尺寸,在服务端会将图像展示到label控件中

执行效果如下:
在这里插入图片描述

  • 7
    点赞
  • 81
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
在C#上位机和单片机之间进行TCP通信数据传输,需要编写两端的代码。下面是一个简单的示例代码,演示了如何在C#上位机和STM32单片机之间进行TCP通信数据传输。 C#上位机代码: ```c# using System; using System.Net; using System.Net.Sockets; using System.Text; public class TcpClientExample { public static void Main() { try { // 创建一个新的TcpClient对象 TcpClient tcpClient = new TcpClient(); // 连接到STM32单片机的IP地址和端口号 tcpClient.Connect(IPAddress.Parse("192.168.1.100"), 1234); // 获取网络流对象 NetworkStream networkStream = tcpClient.GetStream(); // 发送数据到STM32单片机 byte[] sendBytes = Encoding.UTF8.GetBytes("Hello STM32!"); networkStream.Write(sendBytes, 0, sendBytes.Length); // 接收STM32单片机的回复 byte[] receiveBytes = new byte[1024]; int receiveCount = networkStream.Read(receiveBytes, 0, receiveBytes.Length); string receiveString = Encoding.UTF8.GetString(receiveBytes, 0, receiveCount); Console.WriteLine("Received from STM32: {0}", receiveString); // 关闭网络流和TcpClient对象 networkStream.Close(); tcpClient.Close(); } catch (Exception ex) { Console.WriteLine("Exception: {0}", ex); } } } ``` STM32单片机代码(使用ST的HAL库): ```c #include "stm32f4xx_hal.h" #include <string.h> #define TCP_SERVER_PORT 1234 void SystemClock_Config(void); static void MX_GPIO_Init(void); static void MX_USART6_UART_Init(void); static void MX_ETH_Init(void); int main(void) { HAL_Init(); SystemClock_Config(); MX_GPIO_Init(); MX_USART6_UART_Init(); MX_ETH_Init(); // 创建一个TCP服务器 int serverSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (serverSocket < 0) { Error_Handler(); } // 绑定服务器IP地址和端口号 struct sockaddr_in serverAddr; memset(&serverAddr, 0, sizeof(serverAddr)); serverAddr.sin_family = AF_INET; serverAddr.sin_addr.s_addr = htonl(INADDR_ANY); serverAddr.sin_port = htons(TCP_SERVER_PORT); if (bind(serverSocket, (struct sockaddr *)&serverAddr, sizeof(serverAddr)) < 0) { Error_Handler(); } // 监听客户端连接请求 if (listen(serverSocket, 1) < 0) { Error_Handler(); } while (1) { // 接受客户端连接请求 struct sockaddr_in clientAddr; socklen_t clientAddrLen = sizeof(clientAddr); int clientSocket = accept(serverSocket, (struct sockaddr *)&clientAddr, &clientAddrLen); if (clientSocket < 0) { Error_Handler(); } // 接收客户端发送的数据 char buf[1024]; int rcvCnt = recv(clientSocket, buf, sizeof(buf), 0); if (rcvCnt > 0) { printf("Received from C#: %s\n", buf); // 发送回复给客户端 char *sendStr = "Hello C#!"; int sendCnt = send(clientSocket, sendStr, strlen(sendStr), 0); if (sendCnt < 0) { Error_Handler(); } } // 关闭客户端连接 close(clientSocket); } } ``` 注意:以上代码仅供参考,实际使用时需要根据自己的需求进行修改。在实际应用中,还需要考虑网络传输的稳定性和安全性等问题。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值