在龙芯1c上用RT-Thread上的lwip NETCONN接口实现socket编程

本文重点讨论在龙芯1c上如何利用RT-Thread下的lwip NETCONN接口实现socket编程。至于RT-Thread下龙芯1c网卡驱动和lwip的移植不在本文讨论范围之内,有兴趣的可以移步到https://github.com/chinesebear/rtt-net,RT-Thread下龙芯1c的网卡驱动和lwip的移植是网友chinesebear完成的,本文的测试示例也是chinesebear实现的,只是chinesebear没有写成博文的形式,为了能够在百度上搜到,特此写成了博文形式。网友chinesebear还有一些在RT-Thread使用龙芯1c的例子,请移步到https://github.com/chinesebear/rtt-examples。

龙芯1c的网卡驱动已提交到RT-Thread官方git(https://github.com/RT-Thread/rt-thread)了,RT-Thread默认会初始化网口,初始化函数为rt_hw_eth_init(),已在函数rt_init_thread_entry()中默认调用了。socket编程时,只需要创建一个线程,然后调用lwip的NETCONN接口编程即可。假设已经对lwip有一定了解了,如果不了解,请移步到《NETCONN编程接口简介 LWIP(一) 》http://blog.csdn.net/feather_wch/article/details/50473933

IP地址

查看IP地址

在RT-Thread的msh下使用命令ifconfig查看当前IP地址,如下

在龙芯1c上用RT-Thread上的lwip NETCONN接口实现socket编程_第1张图片


修改IP地址

Ip地址在头文件“rtconfig.h”中修改,比如将板子的IP设为192.168.1.254,修改后的源码如下

在龙芯1c上用RT-Thread上的lwip NETCONN接口实现socket编程_第2张图片


Socket编程示例

本文通过在龙芯1c的板子上,新建两个RT-Thread线程,分别用tcp和udp实现echo(回显)的功能,即收到什么返回什么。另外,在虚拟机的linux上用socket编程来测试,即linux下用c实现的小程序先发送一个字符串,然后看看龙芯1c板子是否返回通用的字符串。
不废话了,直接上源码

源码清单

RT-Thread下的源码

在RT-Thread下,只需要在源文件“bsp\ls1cdev\applications\application.c”中,新建线程“tcpecho”和“udpecho”即可。具体源码如下

/*
 * File      : application.c
 * This file is part of RT-Thread RTOS
 * COPYRIGHT (C) 2006-2012, RT-Thread Develop Team
 *
 * The license and distribution terms for this file may be
 * found in the file LICENSE in this distribution or at
 * http://www.rt-thread.org/license/LICENSE
 *
 * Change Logs:
 * Date                Author         Notes
 * 2010-06-25          Bernard        first version
 * 2011-08-08          lgnq           modified for Loongson LS1B
 * 2015-07-06          chinesebear    modified for Loongson LS1C
 */

#include 
#include 
#include "net/synopGMAC.h"
#include 

#define TCP_ECHO_PORT   8000
#define UDP_ECHO_PORT   8000

#define printf rt_kprintf

static void DumpData(const rt_uint8_t *pcStr,rt_uint8_t *pucBuf,rt_uint32_t usLen)
{

    rt_uint32_t i;
    rt_uint8_t acTmp[17];
    rt_uint8_t *p;
    rt_uint8_t *pucAddr = pucBuf;

    if(pcStr)
    {
        printf("%s: length = %d [0x%X]\r\n", pcStr, usLen, usLen);
    }
    if(usLen == 0)
    {
        return;
    }
    p = acTmp;
    printf("%p  ", pucAddr);
    for(i=0;i=0x20) && (pucBuf[i]<0x7F))
        {
            *p++ = pucBuf[i];
        }
        else
        {
            *p++ = '.';
        }
        if((i+1)%16==0)
        {
            *p++ = 0;//string end
            printf("        | %s", acTmp);
            p = acTmp;

            printf("\r\n");

            if((i+1) < usLen)
            {
                pucAddr += 16;
                printf("%p  ", pucAddr);
            }
        }
        else if((i+1)%8==0)
        {
            printf("- ");
        }
    }
    if(usLen%16!=0)
    {
        for(i=usLen%16;i<16;i++)
        {
            printf("   ");
            if(((i+1)%8==0) && ((i+1)%16!=0))
            {
                printf("- ");
            }
        }
        *p++ = 0;//string end
        printf("        | %s", acTmp);
        printf("\r\n");
    }
}

static int rt_netconn_recv(struct netconn *conn, struct netbuf **new_buf)
{
	err_t err;
	err = netconn_recv(conn,new_buf);
	if(*new_buf) 
		return 1;
	else 
		return 0;
}
void rt_tcpecho_entry(void *parameter)
{
	struct netconn *conn, *newconn;
	err_t err;
	struct netbuf *buf;
	void *data;
	u16_t len;
	rt_kprintf("tcpecho server start...\r\n");
	/* Create a new connection identifier. */
	conn = netconn_new(NETCONN_TCP);
	/* Bind connection to well known port number 7. */
	netconn_bind(conn, IP_ADDR_ANY, TCP_ECHO_PORT);
	/* Tell connection to go into listening mode. */
	netconn_listen(conn);
	for(;;)
	{
		/* Grab new connection. */
		err = netconn_accept(conn,&newconn);
		/* Process the new connection. */
		if(newconn != NULL)
		{
			while(rt_netconn_recv(newconn,&buf))
			{
				do
				{
					netbuf_data(buf, &data, &len);
					DumpData("tcpecho packet",data,len);
					err = netconn_write(newconn, data, len, NETCONN_COPY);
					if(err != ERR_OK)
					{
						rt_kprintf("netconn_write(),ret=%d\r\n",err);
					}
				}while(netbuf_next(buf) >= 0);
				netbuf_delete(buf);
				buf = NULL;
			}
		/* Close connection and discard connection identifier. */
		netconn_delete(newconn);
		newconn = NULL;
		}
	}
}
void rt_udpecho_entry(void *parameter)
{	
	struct netconn *conn;	
	struct netbuf *buf;	
	struct ip_addr *addr;	
	unsigned short port;	
    void *data;
    u16_t len = 0;
    
	rt_kprintf("udpecho server start...\r\n");
	conn = netconn_new(NETCONN_UDP);	
	netconn_bind(conn, IP_ADDR_ANY, UDP_ECHO_PORT);	
	for(;;)	
	{       
		/* received data to buffer */		
		netconn_recv(conn,&buf);
        netbuf_data(buf, &data, &len);
        DumpData("udpecho packet", data, len);

        // 延时2秒
        rt_thread_delay(2 * RT_TICK_PER_SECOND);
        
		addr = netbuf_fromaddr(buf);		
		port = netbuf_fromport(buf);        
		/* send the data to buffer */		
		netconn_connect(conn, addr, port);		
		/* reset address, and send to client */	
		buf->addr.addr = 0;
		netconn_send(conn, buf); 
		/* release buffer */		
		netbuf_delete(buf);
        rt_kprintf("[%s] port = %u\n", __FUNCTION__, port);
        rt_kprintf("[%s] send response\n", __FUNCTION__);
	}
}

void rt_init_thread_entry(void *parameter)
{
	
	/* initialization RT-Thread Components */
	rt_components_init();
	rt_hw_eth_init();
}

int rt_application_init(void)
{
	rt_thread_t tid,echo_tid,udpecho_tid;

	/* create initialization thread */
	tid = rt_thread_create("init",
							rt_init_thread_entry, RT_NULL,
							4096, RT_THREAD_PRIORITY_MAX/3, 20);
	if (tid != RT_NULL)
		rt_thread_startup(tid);

	echo_tid = rt_thread_create("tcpecho",
							rt_tcpecho_entry, RT_NULL,
				            4096, 30, 5);
    if (echo_tid != RT_NULL)
            rt_thread_startup(echo_tid);

	udpecho_tid = rt_thread_create("udpecho",
							rt_udpecho_entry, RT_NULL,
				            4096, 30, 5);
    if (udpecho_tid != RT_NULL)
            rt_thread_startup(udpecho_tid);

	return 0;
}

Linux下的配套测试程序

tcpecho的测试程序test_rtt_lwip_tcp_client.c

// client.c

#include 
#include 
#include 
#include 
#include 
#include 


#define MAXLINE         80
#define SERV_PORT       8000

int main(void)
{
    struct sockaddr_in servaddr;
    char buf[MAXLINE] = {0};
    int sockfd;
    char str[] = "ls1c rtt lwip!";
    int len = 0;

    if (0 > (sockfd = socket(AF_INET, SOCK_STREAM, 0)))
    {
        perror("socket");
        return 1;
    }
    bzero(&servaddr, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_addr.s_addr = inet_addr("192.168.1.254");
    servaddr.sin_port = htons(SERV_PORT);

    if (0 > connect(sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr)))
    {
        perror("connect");
        return 1;
    }
    printf("connect to server\n");

    len = send(sockfd, str, strlen(str), 0);
    printf("send ok, len=%d\n", len);
    sleep(1);
    len = recv(sockfd, buf, MAXLINE, 0);
    buf[len] = '\0';
    if (0 == len)
    {
        printf("no byte recv!\n");
    }
    else
    {
        printf("[%s] response from server:%s\n", __FUNCTION__, buf);
    }
    close(sockfd);
    
    return 0;
}




udpecho的测试程序test_rtt_lwip_udp.c

#include 
#include 
#include 
#include 
#include 
#include 
#include 

#define BUF_SIZE            (1024)
#define SERVER_PORT         (8000)

int main(void)
{
    int client_sockfd;
    int len;
    struct sockaddr_in remote_addr;
    int sin_size;
    char str[] = "ls1c rtt lwip udp test!";
    char recv_buf[BUF_SIZE] = {0};

    memset(&remote_addr, 0, sizeof(remote_addr));
    remote_addr.sin_family = AF_INET;
    remote_addr.sin_addr.s_addr = inet_addr("192.168.1.254");
    remote_addr.sin_port = htons(SERVER_PORT);

    if (0 > (client_sockfd = socket(PF_INET, SOCK_DGRAM, 0)))
    {
        perror("socket");
        return 1;
    }

    // 发送字符串
    if (0 > (len = sendto(client_sockfd, str, strlen(str), 0, (struct sockaddr *)&remote_addr, sizeof(struct sockaddr))))
    {
        perror("sendto");
        return 1;
    }
    printf("[%s] sending: %s\n", __FUNCTION__, str);

    if (0 > (len = recvfrom(client_sockfd, recv_buf, BUF_SIZE, 0, NULL, 0)))
    {
        perror("recvfrom");
        return 1;
    }
    printf("[%s] received: %s\n", __FUNCTION__, recv_buf);

    close(client_sockfd);

    return 0;
}





Makefile

all:
	gcc test_rtt_lwip_tcp_client.c -o test_rtt_lwip_tcp_client
	gcc test_rtt_lwip_udp.c -o test_rtt_lwip_udp


测试效果

tcpecho的测试效果

在龙芯1c上用RT-Thread上的lwip NETCONN接口实现socket编程_第3张图片


udpecho的测试效果

在龙芯1c上用RT-Thread上的lwip NETCONN接口实现socket编程_第4张图片



你可能感兴趣的:(在龙芯1c上用RT-Thread上的lwip NETCONN接口实现socket编程)