串口转以太客户端(增加uci、可连接多个服务器)
1、 进入barrier_breaker/package/utils文件夹,新建ttl_client
2、 该目录下的Makefile
- #
- # Copyright (C) OpenWrt.org
- #
- # This is free software, licensed under the GNU General Public License v2.
- # See /LICENSE for more information.
- #
- include $(TOPDIR)/rules.mk
- include $(INCLUDE_DIR)/kernel.mk
- PKG_NAME:=ttl_client
- PKG_RELEASE:=
- PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
- include $(INCLUDE_DIR)/package.mk
- define Package/ttl_client
- SECTION:=utils
- CATEGORY:=Utilities
- TITLE:=serial to tcp
- DEPENDS:=+libuci +libpthread
- endef
- define Package/ttl_client/description
- A client of tcp to serial or serial to tcp
- endef
- define Build/Prepare
- mkdir -p $(PKG_BUILD_DIR)
- $(CP) ./src/* $(PKG_BUILD_DIR)/
- endef
- define Build/Configure
- endef
- define Build/Compile
- $(MAKE) -C $(PKG_BUILD_DIR) \
- CC="$(TARGET_CC)" \
- CFLAGS="$(TARGET_CFLAGS) -Wall -I$(LINUX_DIR)/user_headers/include" \
- LDFLAGS="$(TARGET_LDFLAGS)"
- endef
- define Package/ttl_client/install
- $(INSTALL_DIR) $()/usr/sbin
- $(INSTALL_DIR) $()/etc/config
- $(CP) -rf ./files/ttl2tcp $()/etc/config/
- $(INSTALL_BIN) $(PKG_BUILD_DIR)/ttl_client $()/usr/sbin/
- endef
- $(eval $(call BuildPackage,ttl_client))
3、 新建files文件夹,在该文件夹中新建ttl2tcp配置文件,内容如下
- package ttl2tcp
- config serial device
- #option name ttyUSB0
- #option name ttyS0
- option name ttyATH0
- option baudrate
- option data
- option parity None
- option stop
- option enabled
- config server
- option ipaddr 172.16.1.165
- option port
- config server
- option ipaddr 172.16.1.139
- option port
- config server
- option ipaddr 172.16.1.235
- option port
4、 barrier_breaker/package/utils/ttl_client/src中的Makefile文件,内容如下
- CC = gcc
- CFLAGS = -Wall
- OBJS = ttl_client.o
- all: ttl_client
- %.o: %.c
- $(CC) $(CFLAGS) -c -o $@ $<
- ttl_client: $(OBJS)
- $(CC) -o $@ $(OBJS) -luci -lpthread
- clean:
- rm -f rbcfg *.o
5、 barrier_breaker/package/utils/ttl_client/src中的ttl_client.c
- /*
- * ttl_client
- *
- * tingpan<dktingpan@sina.cn> 2015-05-31
- *
- * this is a client of serial translate to tcp or tcp translate to serial.
- * serial read overtime is 1s
- * every server read overtime is 0.5s,and the most server number is 3.
- */
- #include <stdio.h>
- #include <stdlib.h>
- #include <string.h>
- #include <errno.h>
- #include <sys/types.h>
- #include <sys/socket.h>
- #include <netinet/in.h>
- #include <unistd.h>
- #include <fcntl.h>
- #include <termios.h>
- #include <errno.h>
- #include <strings.h>
- #include <time.h>
- #include <arpa/inet.h>
- #include <pthread.h>
- #include <uci.h>
- #include <semaphore.h>
- #define SER_MAXLINE 128
- #define SOCK_MAXLINE 136//为了应对缓存溢出,多分配一个字节
- #define SERVER_MAXNUM 3
- struct argument
- {
- int fd;
- int sockfd[SERVER_MAXNUM];
- };
- unsigned char on_max;
- struct _options {
- char name[];
- unsigned int baudrate;
- //unsigned int data;
- //unsigned int parity;
- //unsigned int stop;
- unsigned int enabled;
- struct in_addr ipaddr[SERVER_MAXNUM];
- unsigned int port[SERVER_MAXNUM];
- };
- struct _options opt;
- //pthread_mutex_t socket_lock; //互斥锁
- //为了保证用户输入的波特率是个正确的值,所以需要这两个数组验证,对于设置波特率时候,前面要加个B
- int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300,
- B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
- int name_arr[] = {, , , , , , , , ,
- , , , , , , , , , };
- /*-----------------------------------------------------------------------------
- 函数名: set_speed
- 参数: int fd ,int speed
- 返回值: void
- 描述: 设置fd表述符的串口波特率
- *-----------------------------------------------------------------------------*/
- void set_speed(int fd ,int speed)
- {
- struct termios opt;
- int i;
- int status;
- tcgetattr(fd,&opt);
- for(i = ;i < sizeof(speed_arr)/sizeof(int);i++)
- {
- if(speed == name_arr[i]) //找到标准的波特率与用户一致
- {
- tcflush(fd,TCIOFLUSH); //清除IO输入和输出缓存
- cfsetispeed(&opt,speed_arr[i]); //设置串口输入波特率
- cfsetospeed(&opt,speed_arr[i]); //设置串口输出波特率
- status = tcsetattr(fd,TCSANOW,&opt); //将属性设置到opt的数据结构中,并且立即生效
- if(status != )
- perror("tcsetattr fd:"); //设置失败
- return ;
- }
- tcflush(fd,TCIOFLUSH); //每次清除IO缓存
- }
- }
- /*-----------------------------------------------------------------------------
- 函数名: set_parity
- 参数: int fd
- 返回值: int
- 描述: 设置fd表述符的奇偶校验
- *-----------------------------------------------------------------------------*/
- int set_parity(int fd)
- {
- struct termios opt;
- if(tcgetattr(fd,&opt) != ) //或许原先的配置信息
- {
- perror("Get opt in parity error:");
- return -;
- }
- /*通过设置opt数据结构,来配置相关功能,以下为八个数据位,不使能奇偶校验*/
- opt.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
- | INLCR | IGNCR | ICRNL | IXON);
- opt.c_oflag &= ~OPOST;
- opt.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
- opt.c_cflag &= ~(CSIZE | PARENB);
- opt.c_cflag |= CS8;
- tcflush(fd,TCIFLUSH); //清空输入缓存
- if(tcsetattr(fd,TCSANOW,&opt) != )
- {
- perror("set attr parity error:");
- return -;
- }
- return ;
- }
- /*-----------------------------------------------------------------------------
- 函数名: serial_init
- 参数: char *dev_path,int speed,int is_block
- 返回值: 初始化成功返回打开的文件描述符
- 描述: 串口初始化,根据串口文件路径名,串口的速度,和串口是否阻塞,block为1表示阻塞
- *-----------------------------------------------------------------------------*/
- int serial_init(char *dev_path,int speed,int is_block)
- {
- int fd;
- int flag;
- flag = ;
- flag |= O_RDWR; //设置为可读写的串口属性文件
- if(is_block == )
- flag |=O_NONBLOCK; //若为0则表示以非阻塞方式打开
- fd = open(dev_path,flag); //打开设备文件
- if(fd < )
- {
- perror("Open device file err:");
- close(fd);
- return -;
- }
- /*打开设备文件后,下面开始设置波特率*/
- set_speed(fd,speed); //考虑到波特率可能被单独设置,所以独立成函数
- /*设置奇偶校验*/
- if(set_parity(fd) != )
- {
- perror("set parity error:");
- close(fd); //一定要关闭文件,否则文件一直为打开状态
- return -;
- }
- return fd;
- }
- /*-----------------------------------------------------------------------------
- 函数名: serial_send
- 参数: int fd,char *str,unsigned int len
- 返回值: 发送成功返回发送长度,否则返回小于0的值
- 描述: 向fd描述符的串口发送数据,长度为len,内容为str
- *-----------------------------------------------------------------------------*/
- int serial_send(int fd,char *str,unsigned int len)
- {
- int ret;
- if(len > strlen(str)) //判断长度是否超过str的最大长度
- len = strlen(str);
- ret = write(fd,str,len);
- if(ret < )
- {
- perror("serial send err:");
- return -;
- }
- return ret;
- }
- /*-----------------------------------------------------------------------------
- 函数名: serial_read
- 参数: int fd,char *str,unsigned int len,unsigned int timeout
- 返回值: 在规定的时间内读取数据,超时则退出,超时时间为ms级别
- 描述: 向fd描述符的串口接收数据,长度为len,存入str,timeout 为超时时间
- *-----------------------------------------------------------------------------*/
- int serial_read(int fd, char *str, unsigned int len, unsigned int timeout)
- {
- fd_set rfds;
- struct timeval tv;
- int ret; //每次读的结果
- int sret; //select监控结果
- int readlen = ; //实际读到的字节数
- char * ptr;
- ptr = str; //读指针,每次移动,因为实际读出的长度和传入参数可能存在差异
- FD_ZERO(&rfds); //清除文件描述符集合
- FD_SET(fd,&rfds); //将fd加入fds文件描述符,以待下面用select方法监听
- /*传入的timeout是ms级别的单位,这里需要转换为struct timeval 结构的*/
- tv.tv_sec = timeout / ;
- tv.tv_usec = (timeout%)*;
- /*防止读数据长度超过缓冲区*/
- //if(sizeof(&str) < len)
- // len = sizeof(str);
- /*开始读*/
- while(readlen < len)
- {
- sret = select(fd+,&rfds,NULL,NULL,&tv); //检测串口是否可读
- if(sret == -) //检测失败
- {
- perror("select:");
- break;
- }
- else if(sret > ) //<SPAN style="WHITE-SPACE: pre"> </SPAN>//检测成功可读
- {
- ret = read(fd,ptr,); //第三个参数为请求读取的字节数
- if(ret < )
- {
- perror("read err:");
- break;
- }
- else if(ret == )
- break;
- readlen += ret; //更新读的长度
- ptr += ret; //更新读的位置
- }
- else //超时 sret == 0 ,没填满buf也退出循环
- {
- printf("timeout!\n");
- break;
- }
- }
- return readlen;
- }
- /**
- * socket_read: 读取tcp数据
- * @fd: socket文件描述符
- * @str:将读到的数据存放在该地址
- * @len:申请读取的字符长度
- * @timeout:超时时间,单位ms
- */
- int socket_read(int fd, char *str, unsigned int len, unsigned int timeout)
- {
- fd_set fdsr;
- struct timeval tv;
- int readlen = ;
- char * ptr;
- int ret;
- ptr = str;
- // initialize file descriptor set
- FD_ZERO(&fdsr);//每次循环都要清空
- FD_SET(fd, &fdsr);
- tv.tv_sec = timeout / ;
- tv.tv_usec = (timeout%)*;
- while(readlen < len){
- ret = select(fd + , &fdsr, NULL, NULL, &tv);
- if (ret < ) {
- perror("select");
- //break;
- exit(-);
- } else if (ret == ) {
- printf("timeout\n");
- break;
- }
- //每次申请读取8个字节,但事实上是按发送端每次发送的字符串长度来确定的,如果长度小于8,则每次读取实际长度,如果大于8,则读取8字节。
- //recv多少就从缓冲区中删除多少,剩下的数据可以在下次recv时得到
- //即使子线程挂起,也一直有数据可以读,数据不丢失,真正的接收数据是协议来完成的,存放在s的接收缓冲中。
- ret = recv(fd, ptr, , );//申请8个字节
- if (ret <= ) {//如果连接已中止,返回0。如果发生错误,返回-1
- printf("client close\n");
- close(fd);
- FD_CLR(fd, &fdsr);
- fd = ;
- } else {
- readlen +=ret;
- ptr += ret;
- //printf("the ret length is:%d\n",readlen);
- }
- }
- return readlen;
- }
- /**
- * read_config: 读取配置文件
- * @popt: 配置信息保存的结构体
- */
- static int read_config(struct _options *popt)
- {
- static struct uci_context *ctx;
- struct uci_ptr ptr;
- char a[];
- char i;
- unsigned char server_num = ;
- ctx = uci_alloc_context();
- //读取设备名称
- //if ((strcpy(a, "ttl2tcp.device.name") == NULL)
- if ((strncpy(a, "ttl2tcp.device.name", sizeof(a)) == NULL)
- //if (!snprintf(a,sizeof(a),"ttl2tcp.%s.baudrate",SERNAME)
- || (uci_lookup_ptr(ctx, &ptr, a, true) != UCI_OK)) {
- printf("Read ttl2tcp.device.name failed! exit.\n");
- exit(-);
- }
- if (ptr.o) {
- strncpy(popt->name, ptr.o->v.string, sizeof(popt->name));
- } else {
- printf("ttl2tcp.device.name Not found!\n");
- }
- //读取串口波特率
- if ((strncpy(a, "ttl2tcp.device.baudrate", sizeof(a)) == NULL)
- //if (!snprintf(a,sizeof(a),"ttl2tcp.%s.baudrate",SERNAME)
- || (uci_lookup_ptr(ctx, &ptr, a, true) != UCI_OK)) {
- printf("Read tttl2tcp.device.baudrate failed! exit.\n");
- exit(-);
- }
- if (ptr.o) {
- popt->baudrate = strtol(ptr.o->v.string, NULL, );
- } else {
- printf("ttl2tcp.device.baudrate Not found!\n");
- }
- //是否使能
- //if (!snprintf(a,sizeof(a),"ttl2tcp.%s.enabled",SERNAME)
- if ((strncpy(a, "ttl2tcp.device.enabled", sizeof(a)) == NULL)
- || (uci_lookup_ptr(ctx, &ptr, a, true) != UCI_OK)) {
- printf("Read ttl2tcp.device.enabled failed! exit.\n");
- exit(-);
- }
- if (ptr.o) {
- popt->enabled = strtol(ptr.o->v.string, NULL, );
- } else {
- printf("ttl2tcp.device.enabled Not found!\n");
- }
- for(i=; i<SERVER_MAXNUM; i++){
- //读取ip地址
- //if ((strncpy(a, "ttl2tcp.@server[0].ipaddr",sizeof(a)) == NULL)
- if (!snprintf(a,sizeof(a),"ttl2tcp.@server[%d].ipaddr",i)
- || (uci_lookup_ptr(ctx, &ptr, a, true) != UCI_OK)) {
- printf("Read ttl2tcp.@server[%d].ipaddr failed! exit.\n",i);
- exit(-);
- }
- if (ptr.o) {
- unsigned int laddr;
- laddr = inet_addr(ptr.o->v.string);//因为ipaddr为网络字节顺序,大端字节序,而输入的为主机字节序
- memcpy(&popt->ipaddr[i], &laddr, );
- } else {
- printf("ttl2tcp.@server[%d].ipaddr Not found!\n",i);
- }
- //读取port
- //if ((strcpy(a, "ttl2tcp.@server[0].port") == NULL)
- if (!snprintf(a,sizeof(a),"ttl2tcp.@server[%d].port",i)
- || (uci_lookup_ptr(ctx, &ptr, a, true) != UCI_OK)) {
- printf("Read ttl2tcp.@server[%d].port failed! exit.\n",i);
- exit(-);
- }
- if (ptr.o) {
- popt->port[i] = strtol(ptr.o->v.string, NULL, );
- server_num++;
- } else {
- printf("ttl2tcp.@server[%d].port Not found!\n",i);
- }
- }
- uci_free_context(ctx);
- return server_num;
- }
- /**
- * conn_nonb: 非阻塞connect
- * @sockfd: socket文件描述符
- * @saptr:指向数据结构sockaddr的指针,其中包括目的端口和IP地址
- * @salen:sockaddr的长度
- * @nsec:超时时间,单位ms
- */
- int conn_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen, int nsec)
- {
- int flags, n, error, code;
- socklen_t len;
- fd_set wset;
- struct timeval tval;
- flags = fcntl(sockfd, F_GETFL, );
- fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
- error = ;
- if ((n = connect(sockfd, saptr, salen)) == ) { //马上连接成功,可能性小
- printf("conn_nonb success!\n");
- goto done;
- }else if (n < && errno != EINPROGRESS){ //多次连接或服务端没开启,出错 ,第一次一般执行不到该处。
- printf("conn_nonb error!\n");
- return (-);
- }
- /* Do whatever we want while the connect is taking place */
- //连接建立已经启动,但是尚未完成
- FD_ZERO(&wset);
- FD_SET(sockfd, &wset);
- tval.tv_sec = nsec;
- tval.tv_usec = ;
- //printf("conn_nonb select start!\n");
- if ((n = select(sockfd+, NULL, &wset, //有连接要处理
- NULL, nsec ? &tval : NULL)) == ) {
- close(sockfd); /* timeout */
- errno = ETIMEDOUT;
- printf("conn_nonb select timeout!\n");
- return (-);
- }
- if (FD_ISSET(sockfd, &wset)) {
- len = sizeof(error);
- code = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);
- /* 如果发生错误,Solaris实现的getsockopt返回-1,
- * 把pending error设置给errno. Berkeley实现的
- * getsockopt返回0, pending error返回给error.
- * 我们需要处理这两种情况 */
- if (code < || error) {
- close(sockfd);
- if (error)
- errno = error;
- printf("conn_nonb getsockopt error!\n");
- return (-);
- }
- } else {
- fprintf(stderr, "select error: sockfd not set");
- exit();
- }
- done:
- fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
- return ();
- }
- void *socket_thread(void *arg)
- {
- char sockbuf[SOCK_MAXLINE];
- int sreadlen = ;
- int freadlen = ;
- unsigned char i;
- struct argument thread_arg;
- thread_arg = *(struct argument *)arg;
- memset(sockbuf, , sizeof(sockbuf));
- while()
- {
- for (i=; i<on_max;i++)
- {
- //pthread_mutex_lock(&socket_lock);//lock
- sreadlen = socket_read(thread_arg.sockfd[i], sockbuf, SOCK_MAXLINE-, );//为了防止缓存溢出,少读取一个字节
- printf("the sockbuf is:%s\n", sockbuf);//打印出数据
- printf("the sockbuf length is:%d\n",sreadlen);
- freadlen = serial_send(thread_arg.fd,sockbuf,sreadlen);
- printf("send %d bytes!\n",freadlen);
- memset(sockbuf, , sizeof(sockbuf));
- //pthread_mutex_unlock(&socket_lock);//unlock
- usleep();
- }
- }
- }
- int main(int argc, char** argv)
- {
- //串口变量定义
- int fd;
- char str[]="hello linux serial!"; //字符串初始化
- char serbuf[SER_MAXLINE];
- int readlen;
- char dev_path[];
- // socket变量定义
- int sockfd[SERVER_MAXNUM];//SERVER_MAXNUM
- struct sockaddr_in servaddr[SERVER_MAXNUM];//SERVER_MAXNUM
- unsigned char i;
- unsigned char on_sockfd[SERVER_MAXNUM] = {};
- on_max = ;//最大上线个数
- //多线程
- pthread_t thread;
- int mret;
- struct argument arg;
- //读取配置文件
- unsigned char server_num;//服务器个数初始化
- server_num = read_config(&opt);
- if (opt.enabled != )
- {
- printf("do not enable ttl_client!\n");
- exit(-);
- }
- //串口初始化
- if (!snprintf(dev_path,sizeof(dev_path),"/dev/%s",opt.name)
- || (fd = serial_init(dev_path,opt.baudrate,)) < )
- {
- perror("serial init err:");
- return -;
- }
- memset(serbuf, , sizeof(serbuf));
- //socket始化
- for (i=; i<server_num; i++)
- {
- printf("socket init %d/%d\n",i,server_num);
- if( (sockfd[i] = socket(AF_INET, SOCK_STREAM, )) < )
- {
- printf("create socket2 error: %s(errno: %d)\n", strerror(errno),errno);
- exit();
- }
- memset(&servaddr[i], , sizeof(servaddr[i]));
- servaddr[i].sin_family = AF_INET;
- servaddr[i].sin_port = htons(opt.port[i]);
- servaddr[i].sin_addr = opt.ipaddr[i];//与配置文件有关,注意配置文件要正确
- //if( connect(sockfd[i], (struct sockaddr*)&servaddr[i], sizeof(servaddr[i])) < 0)
- //非阻塞连接10s,如果前一个sockfd没有connect成功,则下次将建立一样的文件描述符号
- if( conn_nonb(sockfd[i], (struct sockaddr*)&servaddr[i], sizeof(servaddr[i]),) < )
- {
- printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
- continue;
- //exit(0);
- }
- on_sockfd[on_max++] = i;
- printf("send msg to server[%d]: %d\n",i,on_max-);//on_max-1为上线客户端的新编号
- //socket发送
- if( send(sockfd[i], str, strlen(str), ) < )
- {
- printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
- exit();
- }
- }
- //如果没有一个服务器上线
- if (on_max == )
- {
- exit();
- }
- //锁
- //pthread_mutex_init(&socket_lock, NULL);
- //创建多线程
- arg.fd=fd;
- for (i=; i<on_max;i++)
- {
- arg.sockfd[i]=sockfd[on_sockfd[i]];
- }
- mret = pthread_create(&thread, NULL, socket_thread, (void *)(long)&arg);
- if (mret != )
- {
- printf("Create thread failed\n");
- exit(mret);
- }
- printf("Create thread\n");
- //串口转tcp
- while()
- {
- readlen = serial_read(fd,serbuf,SER_MAXLINE,);//1s内如果数据没有装满buf,则读取完毕。 如果数据量大,则读取的速度也越快。
- printf("the serbuf is :%s\n",serbuf);
- printf("the serbuf length is :%d\n",readlen);
- for (i=; i<on_max;i++)
- {
- printf("sockfd[%d]:%d\n",i,sockfd[on_sockfd[i]]);
- if( send(sockfd[on_sockfd[i]], serbuf, readlen, ) < )//serbuf中有数据可以发送才会执行这条语句
- {
- printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);//服务端断掉,则发送失败。
- exit();
- }
- }
- memset(serbuf, , sizeof(serbuf));
- sleep();
- }
- //退出
- close(fd);
- for (i=; i<server_num;i++)
- close(sockfd[i]);
- exit();
- }
串口转以太客户端(增加uci、可连接多个服务器)的更多相关文章
- Redis02 Redis客户端之Java、连接远程Redis服务器失败
1 查看支持Java的redis客户端 本博文采用 Jedis 作为redis客户端,采用 commons-pool2 作为连接redis服务器的连接池 2 下载相关依赖与实战 2.1 到 Repos ...
- HTTP实现长连接(TTP1.1和HTTP1.0相比较而言,最大的区别就是增加了持久连接支持Connection: keep-alive)
HTTP实现长连接 HTTP是无状态的 也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接.如果客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web ...
- ubuntu客户端使用RDP协议连接windows服务器
如果服务器是linux或unix,可以使用ssh远程连接服务器.也有服务器是windows的,通常使用RDP协议进行连接. 1 环境 客户端:ubuntu14.04 LST 服务器:windows ...
- 通过使用精简客户端,且不需要安装的客户端,配合PLSQL连接oracle数据库
通过使用精简客户端,且不需要安装的客户端,配合PLSQL连接oracle数据库. 首先下载安装包在Oralce官方网站上下载Oracle Instantclient Basic package.地址如 ...
- 3 Oracle 32位客户端安装及arcgis连接
关于Oracle服务器端安装及配置的过程详见第2篇文章,链接如下:http://www.cnblogs.com/gistrd/p/8494292.html,本篇介绍客户端安装配置及连接arcgis过程 ...
- 局域网内客户端无法使用机器名连接SQLServer服务器
在生产环境中有时会要求使用机器名连接SQLServer服务器,但有时捣好久都没法连上~ 针对这个问题做个简短记录,防止以后自己再遇到记不起原因,也方便一下其他同行! 废话不多说,作为工作多年的老家伙了 ...
- SQLServer 2005客户端远程连接sql2008 数据库服务器
SQL2005客户端远程连接sql2008 数据库服务器 by:授客 QQ:1033553122 准备工作: 客户端所在pc机配置: 配置数据源 控制面板-管理工具-ODBC数据源-系统DSN-添加- ...
- 通过数据库客户端界面工具DBeaver连接Hive
前言 本文讲解如何通过数据库客户端界面工具DBeaver连接hive,并解决驱动下载不下来的问题. 1.为什么使用客户端界面工具 为什么使用客户端界面工具而不用命令行使用hive 通过界面工具查看分析 ...
- 桌面远程连接阿里云服务器(windows)后丧失了双向文件复制粘贴功能的解决方案(第一条博客!)
近日应公司要求,需在windows服务器上架设一个交易中介软件. 过程之一:将软件压缩文件传到服务器上. 问题:在“运行”对话框通过输入'mstsc' 创建远程连接以后,出现本地桌面与服务器之间无法物 ...
随机推荐
- SSL/TLS Server supports TLSv1.0
远程登录服务器后打开注册表编辑器,点开HKEY-LOCAL-MACHINE,SYSTEM,CURRENTCONTROLSET下的Control 找到SecurityProviders下的SCHANNE ...
- Gauss error function
0. error function erf(x)=1π∫−xxe−t2dt" role="presentation">erf(x)=1π−−√∫x−xe−t2dte ...
- Python学习笔记第九周
目录: 一.基础概念 1.paramiko模块 2.进程与线程 1.进程 2.线程 3.进程与线程的区别 4.Python GIL 5.thread模块 6.Join与Daemon 7.线程锁(Mut ...
- 12.2 关闭DLM 自动收集统计信息 (SCM0)ORA-00600之[ksliwat: bad wait time]
一.报错日志 db_alert ORA-: ??????, ??: [ksliwat: bad wait time], [], [], [], [], [], [], [], [], [], [], ...
- SPI有关CPOL和CPHA的时序图
SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置. 时钟极性(CPOL)对传输协议没有重大的影响. 如果CPOL=0,串行同步时钟的空闲状态为低电平: 如果 ...
- [LeetCode&Python] Problem 830. Positions of Large Groups
In a string S of lowercase letters, these letters form consecutive groups of the same character. For ...
- 20155219实验三 敏捷开发与XP实践
实验内容 XP基础 XP核心实践 相关工具 敏捷开发与XP 1.敏捷开发(Agile Development)是一种以人为核心.迭代.循序渐进的开发方法."敏捷流程"是一系列价值观 ...
- SQLI DUMB SERIES-6
less6 输入 ?id=1" 说明双引号未被过滤,输入的id被一对双引号所包围,存在注入点,可以闭合双引号. 而输入正常时 情况和less5相同,因此注入同less5.
- alpha冲刺(1/10)(作废)
前言 队名:旅法师 作业链接 队长博客 燃尽图 会议 站立式会议照片 会议内容 陈晓彬(组长) 昨日进展: 召开会议 安排任务 博客撰写 问题困扰: 没有做项目经理的经验,在沟通方面专业知识不够. 心 ...
- linux报错jar包时出现“Exception in thread "main" java.lang.SecurityException: Invalid signature file digest for Manifest main attributes”
linux安装zip命令: yum install zip zip -d demo.jar META-INF/*.RSA META-INF/*.DSA META-INF/*.SF