开发板与PC端虚拟机的Socket基础通信

开发板的主芯片是NXP的imx6ull,PC端虚拟机是运行在VirtualBox环境下的Ubuntu。开发板的以太网口接网线,利用ifconfig查看它的ip地址信息:
在这里插入图片描述
可见其ip地址为192.168.0.104。虚拟机连接的网络和开发板网络是同一个局域网,同样可查到虚拟机的ip信息:
在这里插入图片描述
它的ip地址是192.168.0.103。在开发板上ping虚拟机的ip地址,结果如下:
在这里插入图片描述
可见从开发板侧可以ping通虚拟机。反过来在虚拟机侧ping开发板,如下:
在这里插入图片描述
从结果看也是没有问题的。我们让开发板作为服务端,让虚拟机作为客户端。服务端执行经典的socket、bind、listen和accept等套接字操作流程实现对客户端的监听、接入,客户端则调用socket和connect主动向服务端发起连接请求。连接成功后,客户端从标准输入stdin获取要发送给服务端的数据,服务端接收到数据后给到标准输出,收到exit则服务端发起close。开发板服务端代码如下:

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

#define SERVER_PORT 9876 // server监听在这个端口号

int main(void)
{
    struct sockaddr_in server_addr = {0}; // server套接字结构体
    struct sockaddr_in client_addr = {0}; // client套接字结构体
    char ip_str[20] = {0};
    int sockfd, connfd; // 套接字描述符和已连接描述符
    int addrlen = sizeof(client_addr);
    char recvbuf[512];
    int ret;

	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){ // 以流式套接字socket
        perror("socket error");
        exit(EXIT_FAILURE);		
	}

    server_addr.sin_family = AF_INET;
    server_addr.sin_addr.s_addr = htonl(INADDR_ANY); // 设置可连接ip地址为通配ip
    server_addr.sin_port = htons(SERVER_PORT); // 设置监听端口号
	if((ret = bind(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr))) < 0){
        perror("bind error");
        close(sockfd);
        exit(EXIT_FAILURE);		
	}

	if((ret = listen(sockfd, 50)) < 0){ // 最大可处理的排队待连接客户端数为50
        perror("listen error");
        close(sockfd);
        exit(EXIT_FAILURE);		
	}	

	if((connfd = accept(sockfd, (struct sockaddr *)&client_addr, &addrlen)) < 0){ // 阻塞等待客户端连接
        perror("accept error");
        close(sockfd);
        exit(EXIT_FAILURE);		
	}

    inet_ntop(AF_INET, &client_addr.sin_addr.s_addr, ip_str, sizeof(ip_str)); // 解析客户端ip地址
    printf("客户端主机的IP地址和进程的端口号分别为: %s  %d\n", ip_str, client_addr.sin_port);

    for(;;){ // 处理客户端发来的数据
        memset(recvbuf, 0x0, sizeof(recvbuf));
 
        if((ret = recv(connfd, recvbuf, sizeof(recvbuf), 0)) <= 0){ //读取数据
            perror("recv error");
            close(connfd);
            break;
        }

        printf("server从client获取的数据: %s\n", recvbuf);

        if(strncmp("exit", recvbuf, 4) == 0){
            printf("server exit...\n");
            close(connfd);
            break;
        }
    }

    close(sockfd);
    exit(EXIT_SUCCESS);
}

虚拟机客户端代码如下:

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

#define SERVER_PORT	9876

int main(int argc, char *argv[])
{
    struct sockaddr_in server_addr = {0};
    char buf[512];
    int sockfd;
    int ret;
	
	if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
		perror("socket error");
		exit(EXIT_FAILURE);
	}

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(SERVER_PORT);
    inet_pton(AF_INET, argv[1], &server_addr.sin_addr); // ip地址
    if((ret = connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr))) < 0){
        perror("connect error");
        close(sockfd);
        exit(EXIT_FAILURE);
    }

    printf("服务器连接成功...\n\n");

    for(;;){ // 向服务器发送数据
        memset(buf, 0x0, sizeof(buf));

        printf("Please enter a string: ");
        fgets(buf, sizeof(buf), stdin); // 从标准输入获取

        if((ret = send(sockfd, buf, strlen(buf), 0)) < 0){
            perror("send error");
            break;
        }

        if((strncmp(buf, "exit", 4)) == 0)
            break;
    }

    close(sockfd);
    exit(EXIT_SUCCESS);
}

分别使用gcc和arm-linux-gnueabihf-gcc编译客户端和服务端程序,编译完成后先在开发板启动服务器进程,然后在虚拟机启动客户端进程,若连接成功则在虚拟机端输入字符串并发送,正常情况下可看到开发板侧显示来自虚拟机的数据,如下:
在这里插入图片描述
在这里插入图片描述

  • 2
    点赞
  • 15
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值