Làm cách nào để liên lạc giữa Raspberry Pis bằng WiFi?


7

Làm cách nào để liên lạc giữa 2 Raspberry Pis với WiFi dongle? Tôi đã kết nối 2 khóa WiFi với bộ định tuyến nhưng tôi không biết bước tiếp theo là làm thế nào để khiến chúng giao tiếp. Trong trường hợp này, tôi đang sử dụng mạng cho 2 con chuột siêu nhỏ để liên lạc.


2
Nó hơi phụ thuộc vào những gì bạn đang hỏi - đó có phải là một câu hỏi lập trình không? Hoặc nó kết nối mạng? Bạn có viết một chương trình sẽ trao đổi thông tin giữa hai Pis không? Hoặc bạn có muốn sử dụng phần mềm hiện có (ví dụ: curl) trên PiA để lấy dữ liệu từ máy chủ (ví dụ: Apache httpd) trên PiB không?
ThatBlairGuy

Câu trả lời:


9

Có nhiều cách tiếp cận để thực hiện những gì bạn muốn. Họ cách tôi sẽ mô tả có lẽ sẽ có một đường cong học tập tuy nhiên, vì tôi đã sử dụng C . Hầu hết các thông tin tôi đã sử dụng đến từ này rất hướng dẫn hữu ích .

Với phương pháp này, bạn sẽ cần một máy kháchmáy chủ để liên lạc giữa hai Raspberry Pis. Việc trao đổi thông tin giữa máy khách và máy chủ được tóm tắt trong sơ đồ này:

                                 nhập mô tả hình ảnh ở đây


Đây là một số mã C cho một máy chủ và máy khách. Tất cả các máy chủ này làm là gửi chuỗi "Xin chào, Thế giới! \ N" qua kết nối luồng. Tất cả những gì bạn cần làm để kiểm tra máy chủ này là chạy nó trong một cửa sổ và telnet đến nó từ một cửa sổ khác với:

$ telnet remotehostname 3490

(trong đó remotehostname là tên của máy bạn đang chạy)

Đây là server.cmã:

/*
** server.c -- a stream socket server demo
*/

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

#define PORT "3490"  // the port users will be connecting to

#define BACKLOG 10   // how many pending connections queue will hold

void sigchld_handler(int s)
{
    while(waitpid(-1, NULL, WNOHANG) > 0);
}

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(void)
{
    int sockfd, new_fd;  // listen on sock_fd, new connection on new_fd
    struct addrinfo hints, *servinfo, *p;
    struct sockaddr_storage their_addr; // connector's address information
    socklen_t sin_size;
    struct sigaction sa;
    int yes=1;
    char s[INET6_ADDRSTRLEN];
    int rv;

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;
    hints.ai_flags = AI_PASSIVE; // use my IP

    if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and bind to the first we can
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->ai_protocol)) == -1) {
            perror("server: socket");
            continue;
        }

        if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
                sizeof(int)) == -1) {
            perror("setsockopt");
            exit(1);
        }

        if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("server: bind");
            continue;
        }

        break;
    }

    if (p == NULL)  {
        fprintf(stderr, "server: failed to bind\n");
        return 2;
    }

    freeaddrinfo(servinfo); // all done with this structure

    if (listen(sockfd, BACKLOG) == -1) {
        perror("listen");
        exit(1);
    }

    sa.sa_handler = sigchld_handler; // reap all dead processes
    sigemptyset(&sa.sa_mask);
    sa.sa_flags = SA_RESTART;
    if (sigaction(SIGCHLD, &sa, NULL) == -1) {
        perror("sigaction");
        exit(1);
    }

    printf("server: waiting for connections...\n");

    while(1) {  // main accept() loop
        sin_size = sizeof their_addr;
        new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
        if (new_fd == -1) {
            perror("accept");
            continue;
        }

        inet_ntop(their_addr.ss_family,
            get_in_addr((struct sockaddr *)&their_addr),
            s, sizeof s);
        printf("server: got connection from %s\n", s);

        if (!fork()) { // this is the child process
            close(sockfd); // child doesn't need the listener
            if (send(new_fd, "Hello, world!", 13, 0) == -1)
                perror("send");
            close(new_fd);
            exit(0);
        }
        close(new_fd);  // parent doesn't need this
    }

    return 0;
}

Đây là client.cmã:

/*
** client.c -- a stream socket client demo
*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.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 PORT "3490" // the port client will be connecting to 

#define MAXDATASIZE 100 // max number of bytes we can get at once 

// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa)
{
    if (sa->sa_family == AF_INET) {
        return &(((struct sockaddr_in*)sa)->sin_addr);
    }

    return &(((struct sockaddr_in6*)sa)->sin6_addr);
}

int main(int argc, char *argv[])
{
    int sockfd, numbytes;  
    char buf[MAXDATASIZE];
    struct addrinfo hints, *servinfo, *p;
    int rv;
    char s[INET6_ADDRSTRLEN];

    if (argc != 2) {
        fprintf(stderr,"usage: client hostname\n");
        exit(1);
    }

    memset(&hints, 0, sizeof hints);
    hints.ai_family = AF_UNSPEC;
    hints.ai_socktype = SOCK_STREAM;

    if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
        fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
        return 1;
    }

    // loop through all the results and connect to the first we can
    for(p = servinfo; p != NULL; p = p->ai_next) {
        if ((sockfd = socket(p->ai_family, p->ai_socktype,
                p->ai_protocol)) == -1) {
            perror("client: socket");
            continue;
        }

        if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
            close(sockfd);
            perror("client: connect");
            continue;
        }

        break;
    }

    if (p == NULL) {
        fprintf(stderr, "client: failed to connect\n");
        return 2;
    }

    inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
            s, sizeof s);
    printf("client: connecting to %s\n", s);

    freeaddrinfo(servinfo); // all done with this structure

    if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
        perror("recv");
        exit(1);
    }

    buf[numbytes] = '\0';

    printf("client: received '%s'\n",buf);

    close(sockfd);

    return 0;
}

Bạn có thể đọc thêm về hướng dẫn mà tôi đã liên kết để tìm hiểu cách phát triển giao tiếp nâng cao hơn giữa máy khách và máy chủ.


0

Bạn có thể sử dụng hầu hết mọi ngôn ngữ lập trình yêu thích của mình cho việc này ...

Mỗi trong số chúng có một số loại thư viện truyền thông để tạo Net Sockets, như cổng UART ảo nơi bạn có thể gửi dữ liệu nhị phân hoặc dữ liệu văn bản ở mức cao trong khi các thư viện xử lý lỗi và kiểm soát luồng trong suốt.


0

Nếu bạn muốn chạy WiFi qua Pis mà không phải kết nối Bộ định tuyến (Cơ sở hạ tầng), bạn có thể muốn chúng chạy trên mạng ad-hoc tức là Bạn sẽ không cần Bộ định tuyến và không phải kết nối với Internet.

Cảnh báo

Khi bạn muốn đạt được chế độ ad-hoc đã đề cập ở trên, bạn có thể muốn mua đúng loại Bộ điều hợp WiFi , đặc biệt chạy chế độ ad-hoc, sau đó bạn sẽ phải mua bộ điều hợp WiFi dựa trên Chipset RALINK . Hầu hết cộng đồng sử dụng Bộ điều hợp WiFi EDIMAX 7811UN - rất phù hợp nếu bạn muốn kết nối với chế độ Cơ sở hạ tầng Internet nhưng nếu bạn muốn Pis nói chuyện với nhau thì hãy chắc chắn rằng bạn mua đúng loại Bộ điều hợp WiFi.

Nếu bạn muốn, bạn có thể xem Liên kết này nếu bạn muốn hiểu rõ hơn về vấn đề tôi đang cố gắng giải quyết.

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.