RT-Thread開發之路(3)— UDP通信和TCP客戶端通信
UDP通信和TCP客戶端通信
在之前的基礎上開始:RT-Thread開發之路(2)— 使用at_device軟件包通過ESP8266連接到網絡
一、UDP通信
首先包含需要使用的頭文件:
#include <sys/socket.h>
#include "netdb.h"
然後創建一個socket
/* 創建一個socket,協議簇爲AT Socket 協議棧,類型是SOCK_DGRAM,UDP類型 */
int sock_fd = socket(AF_AT,SOCK_DGRAM,0);
if (sock_fd == -1)
{
rt_kprintf("Socket error\n");
return 0;
}
接下來通過gethostbyname
函數獲得要訪問的遠端IP地址信息
/* 通過函數參數獲得host地址(如果是域名,會做域名解析) */
struct hostent *host;
host = (struct hostent *) gethostbyname("192.168.0.107");
接着設置IP地址端口號等一些信息,發送一個字符串過去
/* 初始化預連接的服務端地址 */
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(12344);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
sendto(sock_fd, "Hello world!", sizeof("Hello world!"), 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
發送完成之後就等待接收了
/* 等待接收對方發送的數據 */
struct sockaddr_in recv_addr;
socklen_t addrlen = sizeof(recv_addr);
char recvbuf[1024] = {0};
ret = recvfrom(sockfd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen); //1024表示本次接收的最大字節數
接收到數據之後將其打印出來:
rt_kprintf("recv :%s \n",recvbuf);
在PC機上打開網絡調試助手,可以收到信息,
然後發送消息到開發板,也可以收到
代碼如下:
#include <rtthread.h>
#include <board.h>
#include <rtdevice.h>
#include <sys/socket.h>
#include "netdb.h"
int main(void)
{
int ret;
/* 創建一個socket,協議簇爲AT Socket 協議棧,類型是SOCK_DGRAM,UDP類型 */
int sock_fd = socket(AF_AT,SOCK_DGRAM,0);
if (sock_fd == -1)
{
rt_kprintf("Socket error\n");
return 0;
}
// 2、綁定本地的相關信息,如果不綁定,則系統會隨機分配一個端口號
struct sockaddr_in local_addr = {0};
local_addr.sin_family = AF_INET; //使用IPv4地址
local_addr.sin_addr.s_addr = inet_addr("192.168.0.103"); //本機IP地址
local_addr.sin_port = htons(12341); //端口
bind(sock_fd, (struct sockaddr*)&local_addr, sizeof(local_addr));//將套接字和IP、端口綁定
/* 通過函數參數獲得host地址(如果是域名,會做域名解析) */
struct hostent *host;
host = (struct hostent *) gethostbyname("192.168.0.107");
/* 初始化預連接的服務端地址 */
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(12344);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
ret = sendto(sock_fd, "Hello world!", sizeof("Hello world!"), 0, (struct sockaddr*)&server_addr, sizeof(server_addr));
if(ret > 0 )
rt_kprintf("send to ok\r\n");
else {
rt_kprintf("send to err \r\n");
}
while (1)
{
/* 等待接收對方發送的數據 */
struct sockaddr_in recv_addr;
socklen_t addrlen = sizeof(recv_addr);
char recvbuf[1024] = {0};
recvfrom(sock_fd, recvbuf, 1024, 0,(struct sockaddr*)&recv_addr,&addrlen); //1024表示本次接收的最大字節數
rt_kprintf("recv :%s \n",recvbuf);
}
/* 關閉這個socket */
closesocket(sock_fd);
return RT_EOK;
}
二、TCP通信
同樣的,包含需要使用的頭文件:
#include <sys/socket.h>
#include "netdb.h"
然後創建一個socket,類型改爲TCP
/* 創建一個socket,協議簇爲AT Socket 協議棧,類型是SOCK_STREAM,TCP類型 */
int sock_fd = socket(AF_AT,SOCK_STREAM,0);
if (sock_fd == -1)
{
rt_kprintf("Socket error\n");
return 0;
}
接下來通過gethostbyname
函數獲得要連接的服務器的IP地址信息
/* 通過函數參數獲得host地址(如果是域名,會做域名解析) */
struct hostent *host;
host = (struct hostent *) gethostbyname("192.168.0.107");
接着設置要連接的服務器的協議棧、IP地址和端口號等一些信息
/* 初始化要連接的服務端地址 */
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(12344);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
然後連接到服務器
/* 連接到服務器 */
if (connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
{
rt_kprintf("Connect fail!\n");
return 0;
}
然後發送一個消息到服務器
/* 發送數據到服務遠端 */
const char send_data[] = "Hello, I am RT-Thread.";
send(sock_fd, send_data, strlen(send_data), 0);
發送完成之後就等待接收了
char recvbuf[1024] = {0};
while (1)
{
/* 等待接收服務端發送過來的數據,最大接收1024個字節 */
ret = recv(sock_fd, recvbuf, sizeof(recvbuf), 0);
/* 6、將接收到的數據打印出來 */
rt_kprintf("Recv date:%s \n",recvbuf);
}
編譯,燒錄,運行,在PC機上打開網絡調試助手,可以收到消息:
接着發送數據,可以看到,開發板接收到了消息
代碼如下:
#include <rtthread.h>
#include <board.h>
#include <rtdevice.h>
#include <sys/socket.h>
#include "netdb.h"
int main(void)
{
int ret;
/* 創建一個socket,協議簇爲AT Socket 協議棧,類型是SOCK_STREAM,TCP類型 */
int sock_fd = socket(AF_AT,SOCK_STREAM,0);
if (sock_fd == -1)
{
rt_kprintf("Socket error\n");
return 0;
}
/* 通過函數參數獲得host地址(如果是域名,會做域名解析) */
struct hostent *host;
host = (struct hostent *) gethostbyname("192.168.0.107");
/* 初始化預連接的服務端地址 */
struct sockaddr_in server_addr;
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(12344);
server_addr.sin_addr = *((struct in_addr *)host->h_addr);
rt_memset(&(server_addr.sin_zero), 0, sizeof(server_addr.sin_zero));
/* 連接到服務器 */
if (connect(sock_fd, (struct sockaddr *)&server_addr, sizeof(struct sockaddr)) < 0)
{
rt_kprintf("Connect fail!\n");
return 0;
}
/* 發送數據到服務遠端 */
const char send_data[] = "Hello, I am RT-Thread.";
send(sock_fd, send_data, strlen(send_data), 0);
char recvbuf[1024] = {0};
while (1)
{
/* 等待接收服務端發送過來的數據,最大接收1024個字節 */
ret = recv(sock_fd, recvbuf, sizeof(recvbuf), 0);
/* 6、將接收到的數據打印出來 */
rt_kprintf("Recv date:%s \n",recvbuf);
}
return RT_EOK;
}