linux下 在tcl中建立udp连接,编译tcl扩展库,并在扩展库中实现udp连接


在tcl中实现udp传输,下面的例子没有完全成功,只能实现单方的接收数据,后续再做补充。
在安装了tcl的环境下,下载tcl-udp安装包解压安装。
代码如下:
//server
package require udp

proc udpEventHandler {sock port} {
    set pkt [read $sock]
    set peer [udp_conf $sock -peer]
    puts "$peer: [string length $pkt] {$pkt}"
    puts $pkt
    return
}

proc writehandler {sock port} {
    puts -nonewline $sock "here is srever"
    return
}

proc udp_listen {port} {
    set srv [udp_open $port]
    fconfigure $srv -buffering none -translation binary
    fileevent $srv readable [list udpEventHandler $srv $port]
    #fileevent $srv writable [list writehandler $srv $port]
    puts "Listening on udp port: [udp_conf $srv -myport]"

    return $srv
}

udp_listen 10234
vwait forever


//client
package require udp

set server 192.168.1.110
set portnum 10234

proc udp_create {host port} {
    set s [udp_open]
    #udp_conf $s $host $port
    fconfigure $s -remote [list $host $port]
    fconfigure $s -buffering none -translation binary
    return $s
}

proc readsock {sock} {
    set pkt [read $sock]
    puts $pkt
    return
}

set sock [udp_create $server $portnum]; #eg localhost 9876
fileevent $sock readable [list readsock $sock]
#after 20000
#puts -nonewline $sock "hello MyData - including binary "
#puts -nonewline $sock [clock seconds]
vwait forever
原本想利用tcl自带的udp进行通讯,但是tcl无法操作内存,于是作罢,上面的例子只能实现一方接收数据,由于这种方法无法实现要求,就没有继续研究。
最终决定在tcl扩展库中实现udp的连接,在扩展库中操作内存。下面的实现是阻塞socket
//tcl_creatsock.c
#include <stdio.h>
#include <stdlib.h>
#include <stdint.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <tcl.h>

static int CreatSock_Cmd(ClientData cdate,Tcl_Interp *interp,int objc,Tcl_Obj *const objv[])
{
    char rsp_buf[2000];
    char buf[2000];
    int socket_id; //套接口描述字
    struct sockaddr_in address;//处理网络通信的地址
    int sin_len;
    uint32_t port_num;
	
    if(objc != 3)
    {
        Tcl_WrongNumArgs(interp,1,objv,"arg1 arg2");
	return TCL_ERROR;
    }

    if(Tcl_GetIntFromObj(interp,objv[2],&port_num) != TCL_OK)
    {
	Tcl_WrongNumArgs(interp,1,objv,"is Int Type");
	return TCL_ERROR;
    }
    Tcl_GetString(objv[1]); 

    bzero(&address,sizeof(address));
    address.sin_family=AF_INET;
    address.sin_addr.s_addr=inet_addr(objv[1]->bytes); //对方ip地址
    address.sin_port=htons(port_num);
    sin_len = sizeof(address);
	
    //创建一个 UDP socket
    socket_id=socket(AF_INET,SOCK_DGRAM,0);//IPV4 SOCK_DGRAM 数据报套接字(UDP协议)
    memset(buf,0,2000);
    memcpy(buf,"here is udp client",strlen("here is udp client"));
	
    sendto(socket_id,buf,2000,0,(struct sockaddr *)&address,sizeof(address));
    recvfrom(socket_id, rsp_buf, 2000, 0, (struct sockaddr *)&address, &sin_len);
    close(socket_id);
    Tcl_SetObjResult(interp,Tcl_NewStringObj(rsp_buf,-1));
    return TCL_OK;
}

int DLLEXPORT Tcl_creatsock_Init(Tcl_Interp *interp)
{
    if(Tcl_InitStubs(interp,TCL_VERSION,0) == NULL)
    {
        return TCL_ERROR;
    }

    if(Tcl_PkgProvide(interp,"my_socket","1.0") == TCL_ERROR)
    {
	return TCL_ERROR;
    }

    Tcl_CreateObjCommand(interp,"CreatSock",CreatSock_Cmd,NULL,NULL);
    return TCL_OK;
}
上面的代码只是一个简单的例子,没有在里面操作内存。扩展库中操作内存在tcl中是可用的,已经通过了实际测试,如果需要操作内存可以在里面随便添加代码。

编译:gcc -shared -o tcl_creatsock.so -DUSE_TCL_STUBS tcl_creatsock.c -I /usr/tcl8.6/include/tcl8.6 -L /usr/tcl8.6/lib -ltclstub8.6 -fPIC
生成:tcl_creatsock.so



//tcl_client.tcl
#!/usr/bin/tclsh

load [file join [pwd] tcl_creatsock[info sharedlibextension]]
puts [CreatSock 192.168.1.110 6789]

运行:tclsh  tcl_client.tcl


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值