1、 进入barrier_breaker/package/utils文件夹,新建ttl_client

2、 该目录下的Makefile

  1. #
  2. # Copyright (C) OpenWrt.org
  3. #
  4. # This is free software, licensed under the GNU General Public License v2.
  5. # See /LICENSE for more information.
  6. #
  7.  
  8. include $(TOPDIR)/rules.mk
  9. include $(INCLUDE_DIR)/kernel.mk
  10.  
  11. PKG_NAME:=ttl_client
  12. PKG_RELEASE:=
  13. PKG_BUILD_DIR := $(BUILD_DIR)/$(PKG_NAME)
  14.  
  15. include $(INCLUDE_DIR)/package.mk
  16.  
  17. define Package/ttl_client
  18. SECTION:=utils
  19. CATEGORY:=Utilities
  20. TITLE:=serial to tcp
  21. DEPENDS:=+libuci +libpthread
  22. endef
  23.  
  24. define Package/ttl_client/description
  25. A client of tcp to serial or serial to tcp
  26. endef
  27.  
  28. define Build/Prepare
  29. mkdir -p $(PKG_BUILD_DIR)
  30. $(CP) ./src/* $(PKG_BUILD_DIR)/
  31. endef
  32.  
  33. define Build/Configure
  34. endef
  35.  
  36. define Build/Compile
  37. $(MAKE) -C $(PKG_BUILD_DIR) \
  38. CC="$(TARGET_CC)" \
  39. CFLAGS="$(TARGET_CFLAGS) -Wall -I$(LINUX_DIR)/user_headers/include" \
  40. LDFLAGS="$(TARGET_LDFLAGS)"
  41. endef
  42.  
  43. define Package/ttl_client/install
  44. $(INSTALL_DIR) $()/usr/sbin
  45. $(INSTALL_DIR) $()/etc/config
  46. $(CP) -rf ./files/ttl2tcp $()/etc/config/
  47. $(INSTALL_BIN) $(PKG_BUILD_DIR)/ttl_client $()/usr/sbin/
  48. endef
  49.  
  50. $(eval $(call BuildPackage,ttl_client))

3、 新建files文件夹,在该文件夹中新建ttl2tcp配置文件,内容如下

  1. package ttl2tcp
  2.  
  3. config serial device
  4. #option name ttyUSB0
  5. #option name ttyS0
  6. option name ttyATH0
  7. option baudrate
  8. option data
  9. option parity None
  10. option stop
  11. option enabled
  12.  
  13. config server
  14. option ipaddr 172.16.1.165
  15. option port
  16.  
  17. config server
  18. option ipaddr 172.16.1.139
  19. option port
  20.  
  21. config server
  22. option ipaddr 172.16.1.235
  23. option port

4、 barrier_breaker/package/utils/ttl_client/src中的Makefile文件,内容如下

  1. CC = gcc
  2. CFLAGS = -Wall
  3. OBJS = ttl_client.o
  4.  
  5. all: ttl_client
  6.  
  7. %.o: %.c
  8. $(CC) $(CFLAGS) -c -o $@ $<
  9.  
  10. ttl_client: $(OBJS)
  11. $(CC) -o $@ $(OBJS) -luci -lpthread
  12.  
  13. clean:
  14. rm -f rbcfg *.o

5、 barrier_breaker/package/utils/ttl_client/src中的ttl_client.c

  1. /*
  2. * ttl_client
  3. *
  4. * tingpan<dktingpan@sina.cn> 2015-05-31
  5. *
  6. * this is a client of serial translate to tcp or tcp translate to serial.
  7. * serial read overtime is 1s
  8. * every server read overtime is 0.5s,and the most server number is 3.
  9. */
  10.  
  11. #include <stdio.h>
  12. #include <stdlib.h>
  13. #include <string.h>
  14. #include <errno.h>
  15. #include <sys/types.h>
  16. #include <sys/socket.h>
  17. #include <netinet/in.h>
  18. #include <unistd.h>
  19. #include <fcntl.h>
  20. #include <termios.h>
  21. #include <errno.h>
  22. #include <strings.h>
  23. #include <time.h>
  24. #include <arpa/inet.h>
  25. #include <pthread.h>
  26. #include <uci.h>
  27. #include <semaphore.h>
  28.  
  29. #define SER_MAXLINE 128
  30. #define SOCK_MAXLINE 136//为了应对缓存溢出,多分配一个字节
  31. #define SERVER_MAXNUM 3
  32.  
  33. struct argument
  34. {
  35. int fd;
  36. int sockfd[SERVER_MAXNUM];
  37. };
  38. unsigned char on_max;
  39. struct _options {
  40. char name[];
  41. unsigned int baudrate;
  42. //unsigned int data;
  43. //unsigned int parity;
  44. //unsigned int stop;
  45. unsigned int enabled;
  46. struct in_addr ipaddr[SERVER_MAXNUM];
  47. unsigned int port[SERVER_MAXNUM];
  48. };
  49. struct _options opt;
  50. //pthread_mutex_t socket_lock; //互斥锁
  51.  
  52. //为了保证用户输入的波特率是个正确的值,所以需要这两个数组验证,对于设置波特率时候,前面要加个B
  53. int speed_arr[] = { B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300,
  54. B115200, B57600, B38400, B19200, B9600, B4800, B2400, B1200, B300, };
  55.  
  56. int name_arr[] = {, , , , , , , , ,
  57. , , , , , , , , , };
  58.  
  59. /*-----------------------------------------------------------------------------
  60. 函数名: set_speed
  61. 参数: int fd ,int speed
  62. 返回值: void
  63. 描述: 设置fd表述符的串口波特率
  64. *-----------------------------------------------------------------------------*/
  65. void set_speed(int fd ,int speed)
  66. {
  67. struct termios opt;
  68. int i;
  69. int status;
  70.  
  71. tcgetattr(fd,&opt);
  72. for(i = ;i < sizeof(speed_arr)/sizeof(int);i++)
  73. {
  74. if(speed == name_arr[i]) //找到标准的波特率与用户一致
  75. {
  76. tcflush(fd,TCIOFLUSH); //清除IO输入和输出缓存
  77. cfsetispeed(&opt,speed_arr[i]); //设置串口输入波特率
  78. cfsetospeed(&opt,speed_arr[i]); //设置串口输出波特率
  79.  
  80. status = tcsetattr(fd,TCSANOW,&opt); //将属性设置到opt的数据结构中,并且立即生效
  81. if(status != )
  82. perror("tcsetattr fd:"); //设置失败
  83. return ;
  84. }
  85. tcflush(fd,TCIOFLUSH); //每次清除IO缓存
  86. }
  87. }
  88. /*-----------------------------------------------------------------------------
  89. 函数名: set_parity
  90. 参数: int fd
  91. 返回值: int
  92. 描述: 设置fd表述符的奇偶校验
  93. *-----------------------------------------------------------------------------*/
  94. int set_parity(int fd)
  95. {
  96. struct termios opt;
  97.  
  98. if(tcgetattr(fd,&opt) != ) //或许原先的配置信息
  99. {
  100. perror("Get opt in parity error:");
  101. return -;
  102. }
  103.  
  104. /*通过设置opt数据结构,来配置相关功能,以下为八个数据位,不使能奇偶校验*/
  105. opt.c_iflag &= ~(IGNBRK | BRKINT | PARMRK | ISTRIP
  106. | INLCR | IGNCR | ICRNL | IXON);
  107. opt.c_oflag &= ~OPOST;
  108. opt.c_lflag &= ~(ECHO | ECHONL | ICANON | ISIG | IEXTEN);
  109. opt.c_cflag &= ~(CSIZE | PARENB);
  110. opt.c_cflag |= CS8;
  111.  
  112. tcflush(fd,TCIFLUSH); //清空输入缓存
  113.  
  114. if(tcsetattr(fd,TCSANOW,&opt) != )
  115. {
  116. perror("set attr parity error:");
  117. return -;
  118. }
  119.  
  120. return ;
  121. }
  122. /*-----------------------------------------------------------------------------
  123. 函数名: serial_init
  124. 参数: char *dev_path,int speed,int is_block
  125. 返回值: 初始化成功返回打开的文件描述符
  126. 描述: 串口初始化,根据串口文件路径名,串口的速度,和串口是否阻塞,block为1表示阻塞
  127. *-----------------------------------------------------------------------------*/
  128. int serial_init(char *dev_path,int speed,int is_block)
  129. {
  130. int fd;
  131. int flag;
  132.  
  133. flag = ;
  134. flag |= O_RDWR; //设置为可读写的串口属性文件
  135. if(is_block == )
  136. flag |=O_NONBLOCK; //若为0则表示以非阻塞方式打开
  137.  
  138. fd = open(dev_path,flag); //打开设备文件
  139. if(fd < )
  140. {
  141. perror("Open device file err:");
  142. close(fd);
  143. return -;
  144. }
  145.  
  146. /*打开设备文件后,下面开始设置波特率*/
  147. set_speed(fd,speed); //考虑到波特率可能被单独设置,所以独立成函数
  148.  
  149. /*设置奇偶校验*/
  150. if(set_parity(fd) != )
  151. {
  152. perror("set parity error:");
  153. close(fd); //一定要关闭文件,否则文件一直为打开状态
  154. return -;
  155. }
  156.  
  157. return fd;
  158. }
  159. /*-----------------------------------------------------------------------------
  160. 函数名: serial_send
  161. 参数: int fd,char *str,unsigned int len
  162. 返回值: 发送成功返回发送长度,否则返回小于0的值
  163. 描述: 向fd描述符的串口发送数据,长度为len,内容为str
  164. *-----------------------------------------------------------------------------*/
  165. int serial_send(int fd,char *str,unsigned int len)
  166. {
  167. int ret;
  168.  
  169. if(len > strlen(str)) //判断长度是否超过str的最大长度
  170. len = strlen(str);
  171.  
  172. ret = write(fd,str,len);
  173. if(ret < )
  174. {
  175. perror("serial send err:");
  176. return -;
  177. }
  178.  
  179. return ret;
  180. }
  181.  
  182. /*-----------------------------------------------------------------------------
  183. 函数名: serial_read
  184. 参数: int fd,char *str,unsigned int len,unsigned int timeout
  185. 返回值: 在规定的时间内读取数据,超时则退出,超时时间为ms级别
  186. 描述: 向fd描述符的串口接收数据,长度为len,存入str,timeout 为超时时间
  187. *-----------------------------------------------------------------------------*/
  188. int serial_read(int fd, char *str, unsigned int len, unsigned int timeout)
  189. {
  190. fd_set rfds;
  191. struct timeval tv;
  192. int ret; //每次读的结果
  193. int sret; //select监控结果
  194. int readlen = ; //实际读到的字节数
  195. char * ptr;
  196.  
  197. ptr = str; //读指针,每次移动,因为实际读出的长度和传入参数可能存在差异
  198.  
  199. FD_ZERO(&rfds); //清除文件描述符集合
  200. FD_SET(fd,&rfds); //将fd加入fds文件描述符,以待下面用select方法监听
  201.  
  202. /*传入的timeout是ms级别的单位,这里需要转换为struct timeval 结构的*/
  203. tv.tv_sec = timeout / ;
  204. tv.tv_usec = (timeout%)*;
  205.  
  206. /*防止读数据长度超过缓冲区*/
  207. //if(sizeof(&str) < len)
  208. // len = sizeof(str);
  209.  
  210. /*开始读*/
  211. while(readlen < len)
  212. {
  213. sret = select(fd+,&rfds,NULL,NULL,&tv); //检测串口是否可读
  214.  
  215. if(sret == -) //检测失败
  216. {
  217. perror("select:");
  218. break;
  219. }
  220. else if(sret > ) //<SPAN style="WHITE-SPACE: pre"> </SPAN>//检测成功可读
  221. {
  222. ret = read(fd,ptr,); //第三个参数为请求读取的字节数
  223. if(ret < )
  224. {
  225. perror("read err:");
  226. break;
  227. }
  228. else if(ret == )
  229. break;
  230.  
  231. readlen += ret; //更新读的长度
  232. ptr += ret; //更新读的位置
  233. }
  234. else //超时 sret == 0 ,没填满buf也退出循环
  235. {
  236. printf("timeout!\n");
  237. break;
  238. }
  239. }
  240.  
  241. return readlen;
  242. }
  243.  
  244. /**
  245. * socket_read: 读取tcp数据
  246. * @fd: socket文件描述符
  247. * @str:将读到的数据存放在该地址
  248. * @len:申请读取的字符长度
  249. * @timeout:超时时间,单位ms
  250. */
  251. int socket_read(int fd, char *str, unsigned int len, unsigned int timeout)
  252. {
  253. fd_set fdsr;
  254. struct timeval tv;
  255. int readlen = ;
  256. char * ptr;
  257. int ret;
  258. ptr = str;
  259. // initialize file descriptor set
  260. FD_ZERO(&fdsr);//每次循环都要清空
  261. FD_SET(fd, &fdsr);
  262. tv.tv_sec = timeout / ;
  263. tv.tv_usec = (timeout%)*;
  264. while(readlen < len){
  265. ret = select(fd + , &fdsr, NULL, NULL, &tv);
  266. if (ret < ) {
  267. perror("select");
  268. //break;
  269. exit(-);
  270. } else if (ret == ) {
  271. printf("timeout\n");
  272. break;
  273. }
  274. //每次申请读取8个字节,但事实上是按发送端每次发送的字符串长度来确定的,如果长度小于8,则每次读取实际长度,如果大于8,则读取8字节。
  275. //recv多少就从缓冲区中删除多少,剩下的数据可以在下次recv时得到
  276. //即使子线程挂起,也一直有数据可以读,数据不丢失,真正的接收数据是协议来完成的,存放在s的接收缓冲中。
  277. ret = recv(fd, ptr, , );//申请8个字节
  278. if (ret <= ) {//如果连接已中止,返回0。如果发生错误,返回-1
  279. printf("client close\n");
  280. close(fd);
  281. FD_CLR(fd, &fdsr);
  282. fd = ;
  283. } else {
  284. readlen +=ret;
  285. ptr += ret;
  286. //printf("the ret length is:%d\n",readlen);
  287. }
  288. }
  289. return readlen;
  290. }
  291.  
  292. /**
  293. * read_config: 读取配置文件
  294. * @popt: 配置信息保存的结构体
  295. */
  296. static int read_config(struct _options *popt)
  297. {
  298. static struct uci_context *ctx;
  299. struct uci_ptr ptr;
  300. char a[];
  301. char i;
  302. unsigned char server_num = ;
  303.  
  304. ctx = uci_alloc_context();
  305.  
  306. //读取设备名称
  307. //if ((strcpy(a, "ttl2tcp.device.name") == NULL)
  308. if ((strncpy(a, "ttl2tcp.device.name", sizeof(a)) == NULL)
  309. //if (!snprintf(a,sizeof(a),"ttl2tcp.%s.baudrate",SERNAME)
  310. || (uci_lookup_ptr(ctx, &ptr, a, true) != UCI_OK)) {
  311. printf("Read ttl2tcp.device.name failed! exit.\n");
  312. exit(-);
  313. }
  314. if (ptr.o) {
  315. strncpy(popt->name, ptr.o->v.string, sizeof(popt->name));
  316. } else {
  317. printf("ttl2tcp.device.name Not found!\n");
  318. }
  319.  
  320. //读取串口波特率
  321. if ((strncpy(a, "ttl2tcp.device.baudrate", sizeof(a)) == NULL)
  322. //if (!snprintf(a,sizeof(a),"ttl2tcp.%s.baudrate",SERNAME)
  323. || (uci_lookup_ptr(ctx, &ptr, a, true) != UCI_OK)) {
  324. printf("Read tttl2tcp.device.baudrate failed! exit.\n");
  325. exit(-);
  326. }
  327. if (ptr.o) {
  328. popt->baudrate = strtol(ptr.o->v.string, NULL, );
  329. } else {
  330. printf("ttl2tcp.device.baudrate Not found!\n");
  331. }
  332.  
  333. //是否使能
  334. //if (!snprintf(a,sizeof(a),"ttl2tcp.%s.enabled",SERNAME)
  335. if ((strncpy(a, "ttl2tcp.device.enabled", sizeof(a)) == NULL)
  336. || (uci_lookup_ptr(ctx, &ptr, a, true) != UCI_OK)) {
  337. printf("Read ttl2tcp.device.enabled failed! exit.\n");
  338. exit(-);
  339. }
  340. if (ptr.o) {
  341. popt->enabled = strtol(ptr.o->v.string, NULL, );
  342. } else {
  343. printf("ttl2tcp.device.enabled Not found!\n");
  344. }
  345.  
  346. for(i=; i<SERVER_MAXNUM; i++){
  347. //读取ip地址
  348. //if ((strncpy(a, "ttl2tcp.@server[0].ipaddr",sizeof(a)) == NULL)
  349. if (!snprintf(a,sizeof(a),"ttl2tcp.@server[%d].ipaddr",i)
  350. || (uci_lookup_ptr(ctx, &ptr, a, true) != UCI_OK)) {
  351. printf("Read ttl2tcp.@server[%d].ipaddr failed! exit.\n",i);
  352. exit(-);
  353. }
  354. if (ptr.o) {
  355. unsigned int laddr;
  356. laddr = inet_addr(ptr.o->v.string);//因为ipaddr为网络字节顺序,大端字节序,而输入的为主机字节序
  357. memcpy(&popt->ipaddr[i], &laddr, );
  358. } else {
  359. printf("ttl2tcp.@server[%d].ipaddr Not found!\n",i);
  360. }
  361. //读取port
  362. //if ((strcpy(a, "ttl2tcp.@server[0].port") == NULL)
  363. if (!snprintf(a,sizeof(a),"ttl2tcp.@server[%d].port",i)
  364. || (uci_lookup_ptr(ctx, &ptr, a, true) != UCI_OK)) {
  365. printf("Read ttl2tcp.@server[%d].port failed! exit.\n",i);
  366. exit(-);
  367. }
  368. if (ptr.o) {
  369. popt->port[i] = strtol(ptr.o->v.string, NULL, );
  370. server_num++;
  371. } else {
  372. printf("ttl2tcp.@server[%d].port Not found!\n",i);
  373. }
  374. }
  375. uci_free_context(ctx);
  376. return server_num;
  377. }
  378.  
  379. /**
  380. * conn_nonb: 非阻塞connect
  381. * @sockfd: socket文件描述符
  382. * @saptr:指向数据结构sockaddr的指针,其中包括目的端口和IP地址
  383. * @salen:sockaddr的长度
  384. * @nsec:超时时间,单位ms
  385. */
  386. int conn_nonb(int sockfd, const struct sockaddr *saptr, socklen_t salen, int nsec)
  387. {
  388. int flags, n, error, code;
  389. socklen_t len;
  390. fd_set wset;
  391. struct timeval tval;
  392.  
  393. flags = fcntl(sockfd, F_GETFL, );
  394. fcntl(sockfd, F_SETFL, flags | O_NONBLOCK);
  395.  
  396. error = ;
  397. if ((n = connect(sockfd, saptr, salen)) == ) { //马上连接成功,可能性小
  398. printf("conn_nonb success!\n");
  399. goto done;
  400. }else if (n < && errno != EINPROGRESS){ //多次连接或服务端没开启,出错 ,第一次一般执行不到该处。
  401. printf("conn_nonb error!\n");
  402. return (-);
  403. }
  404.  
  405. /* Do whatever we want while the connect is taking place */
  406. //连接建立已经启动,但是尚未完成
  407. FD_ZERO(&wset);
  408. FD_SET(sockfd, &wset);
  409. tval.tv_sec = nsec;
  410. tval.tv_usec = ;
  411. //printf("conn_nonb select start!\n");
  412. if ((n = select(sockfd+, NULL, &wset, //有连接要处理
  413. NULL, nsec ? &tval : NULL)) == ) {
  414. close(sockfd); /* timeout */
  415. errno = ETIMEDOUT;
  416. printf("conn_nonb select timeout!\n");
  417. return (-);
  418. }
  419.  
  420. if (FD_ISSET(sockfd, &wset)) {
  421. len = sizeof(error);
  422. code = getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &error, &len);
  423. /* 如果发生错误,Solaris实现的getsockopt返回-1,
  424. * 把pending error设置给errno. Berkeley实现的
  425. * getsockopt返回0, pending error返回给error.
  426. * 我们需要处理这两种情况 */
  427. if (code < || error) {
  428. close(sockfd);
  429. if (error)
  430. errno = error;
  431. printf("conn_nonb getsockopt error!\n");
  432. return (-);
  433. }
  434. } else {
  435. fprintf(stderr, "select error: sockfd not set");
  436. exit();
  437. }
  438.  
  439. done:
  440. fcntl(sockfd, F_SETFL, flags); /* restore file status flags */
  441. return ();
  442. }
  443.  
  444. void *socket_thread(void *arg)
  445. {
  446. char sockbuf[SOCK_MAXLINE];
  447. int sreadlen = ;
  448. int freadlen = ;
  449. unsigned char i;
  450. struct argument thread_arg;
  451. thread_arg = *(struct argument *)arg;
  452. memset(sockbuf, , sizeof(sockbuf));
  453. while()
  454. {
  455. for (i=; i<on_max;i++)
  456. {
  457. //pthread_mutex_lock(&socket_lock);//lock
  458. sreadlen = socket_read(thread_arg.sockfd[i], sockbuf, SOCK_MAXLINE-, );//为了防止缓存溢出,少读取一个字节
  459. printf("the sockbuf is:%s\n", sockbuf);//打印出数据
  460. printf("the sockbuf length is:%d\n",sreadlen);
  461. freadlen = serial_send(thread_arg.fd,sockbuf,sreadlen);
  462. printf("send %d bytes!\n",freadlen);
  463. memset(sockbuf, , sizeof(sockbuf));
  464. //pthread_mutex_unlock(&socket_lock);//unlock
  465. usleep();
  466. }
  467. }
  468. }
  469.  
  470. int main(int argc, char** argv)
  471. {
  472. //串口变量定义
  473. int fd;
  474. char str[]="hello linux serial!"; //字符串初始化
  475. char serbuf[SER_MAXLINE];
  476. int readlen;
  477. char dev_path[];
  478.  
  479. // socket变量定义
  480. int sockfd[SERVER_MAXNUM];//SERVER_MAXNUM
  481. struct sockaddr_in servaddr[SERVER_MAXNUM];//SERVER_MAXNUM
  482. unsigned char i;
  483. unsigned char on_sockfd[SERVER_MAXNUM] = {};
  484. on_max = ;//最大上线个数
  485.  
  486. //多线程
  487. pthread_t thread;
  488. int mret;
  489. struct argument arg;
  490.  
  491. //读取配置文件
  492. unsigned char server_num;//服务器个数初始化
  493. server_num = read_config(&opt);
  494. if (opt.enabled != )
  495. {
  496. printf("do not enable ttl_client!\n");
  497. exit(-);
  498. }
  499.  
  500. //串口初始化
  501. if (!snprintf(dev_path,sizeof(dev_path),"/dev/%s",opt.name)
  502. || (fd = serial_init(dev_path,opt.baudrate,)) < )
  503. {
  504. perror("serial init err:");
  505. return -;
  506. }
  507. memset(serbuf, , sizeof(serbuf));
  508.  
  509. //socket始化
  510. for (i=; i<server_num; i++)
  511. {
  512. printf("socket init %d/%d\n",i,server_num);
  513. if( (sockfd[i] = socket(AF_INET, SOCK_STREAM, )) < )
  514. {
  515. printf("create socket2 error: %s(errno: %d)\n", strerror(errno),errno);
  516. exit();
  517. }
  518. memset(&servaddr[i], , sizeof(servaddr[i]));
  519. servaddr[i].sin_family = AF_INET;
  520. servaddr[i].sin_port = htons(opt.port[i]);
  521. servaddr[i].sin_addr = opt.ipaddr[i];//与配置文件有关,注意配置文件要正确
  522.  
  523. //if( connect(sockfd[i], (struct sockaddr*)&servaddr[i], sizeof(servaddr[i])) < 0)
  524. //非阻塞连接10s,如果前一个sockfd没有connect成功,则下次将建立一样的文件描述符号
  525. if( conn_nonb(sockfd[i], (struct sockaddr*)&servaddr[i], sizeof(servaddr[i]),) < )
  526. {
  527. printf("connect error: %s(errno: %d)\n",strerror(errno),errno);
  528. continue;
  529. //exit(0);
  530. }
  531. on_sockfd[on_max++] = i;
  532. printf("send msg to server[%d]: %d\n",i,on_max-);//on_max-1为上线客户端的新编号
  533. //socket发送
  534. if( send(sockfd[i], str, strlen(str), ) < )
  535. {
  536. printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);
  537. exit();
  538. }
  539. }
  540. //如果没有一个服务器上线
  541. if (on_max == )
  542. {
  543. exit();
  544. }
  545.  
  546. //锁
  547. //pthread_mutex_init(&socket_lock, NULL);
  548.  
  549. //创建多线程
  550. arg.fd=fd;
  551. for (i=; i<on_max;i++)
  552. {
  553. arg.sockfd[i]=sockfd[on_sockfd[i]];
  554. }
  555. mret = pthread_create(&thread, NULL, socket_thread, (void *)(long)&arg);
  556. if (mret != )
  557. {
  558. printf("Create thread failed\n");
  559. exit(mret);
  560. }
  561. printf("Create thread\n");
  562.  
  563. //串口转tcp
  564. while()
  565. {
  566. readlen = serial_read(fd,serbuf,SER_MAXLINE,);//1s内如果数据没有装满buf,则读取完毕。 如果数据量大,则读取的速度也越快。
  567. printf("the serbuf is :%s\n",serbuf);
  568. printf("the serbuf length is :%d\n",readlen);
  569. for (i=; i<on_max;i++)
  570. {
  571. printf("sockfd[%d]:%d\n",i,sockfd[on_sockfd[i]]);
  572. if( send(sockfd[on_sockfd[i]], serbuf, readlen, ) < )//serbuf中有数据可以发送才会执行这条语句
  573. {
  574. printf("send msg error: %s(errno: %d)\n", strerror(errno), errno);//服务端断掉,则发送失败。
  575. exit();
  576. }
  577. }
  578. memset(serbuf, , sizeof(serbuf));
  579. sleep();
  580. }
  581. //退出
  582. close(fd);
  583. for (i=; i<server_num;i++)
  584. close(sockfd[i]);
  585. exit();
  586. }

串口转以太客户端(增加uci、可连接多个服务器)的更多相关文章

  1. Redis02 Redis客户端之Java、连接远程Redis服务器失败

    1 查看支持Java的redis客户端 本博文采用 Jedis 作为redis客户端,采用 commons-pool2 作为连接redis服务器的连接池 2 下载相关依赖与实战 2.1 到 Repos ...

  2. HTTP实现长连接(TTP1.1和HTTP1.0相比较而言,最大的区别就是增加了持久连接支持Connection: keep-alive)

    HTTP实现长连接 HTTP是无状态的 也就是说,浏览器和服务器每进行一次HTTP操作,就建立一次连接,但任务结束就中断连接.如果客户端浏览器访问的某个HTML或其他类型的Web页中包含有其他的Web ...

  3. ubuntu客户端使用RDP协议连接windows服务器

    如果服务器是linux或unix,可以使用ssh远程连接服务器.也有服务器是windows的,通常使用RDP协议进行连接. 1  环境 客户端:ubuntu14.04 LST 服务器:windows ...

  4. 通过使用精简客户端,且不需要安装的客户端,配合PLSQL连接oracle数据库

    通过使用精简客户端,且不需要安装的客户端,配合PLSQL连接oracle数据库. 首先下载安装包在Oralce官方网站上下载Oracle Instantclient Basic package.地址如 ...

  5. 3 Oracle 32位客户端安装及arcgis连接

    关于Oracle服务器端安装及配置的过程详见第2篇文章,链接如下:http://www.cnblogs.com/gistrd/p/8494292.html,本篇介绍客户端安装配置及连接arcgis过程 ...

  6. 局域网内客户端无法使用机器名连接SQLServer服务器

    在生产环境中有时会要求使用机器名连接SQLServer服务器,但有时捣好久都没法连上~ 针对这个问题做个简短记录,防止以后自己再遇到记不起原因,也方便一下其他同行! 废话不多说,作为工作多年的老家伙了 ...

  7. SQLServer 2005客户端远程连接sql2008 数据库服务器

    SQL2005客户端远程连接sql2008 数据库服务器 by:授客 QQ:1033553122 准备工作: 客户端所在pc机配置: 配置数据源 控制面板-管理工具-ODBC数据源-系统DSN-添加- ...

  8. 通过数据库客户端界面工具DBeaver连接Hive

    前言 本文讲解如何通过数据库客户端界面工具DBeaver连接hive,并解决驱动下载不下来的问题. 1.为什么使用客户端界面工具 为什么使用客户端界面工具而不用命令行使用hive 通过界面工具查看分析 ...

  9. 桌面远程连接阿里云服务器(windows)后丧失了双向文件复制粘贴功能的解决方案(第一条博客!)

    近日应公司要求,需在windows服务器上架设一个交易中介软件. 过程之一:将软件压缩文件传到服务器上. 问题:在“运行”对话框通过输入'mstsc' 创建远程连接以后,出现本地桌面与服务器之间无法物 ...

随机推荐

  1. SSL/TLS Server supports TLSv1.0

    远程登录服务器后打开注册表编辑器,点开HKEY-LOCAL-MACHINE,SYSTEM,CURRENTCONTROLSET下的Control 找到SecurityProviders下的SCHANNE ...

  2. Gauss error function

    0. error function erf(x)=1π∫−xxe−t2dt" role="presentation">erf(x)=1π−−√∫x−xe−t2dte ...

  3. Python学习笔记第九周

    目录: 一.基础概念 1.paramiko模块 2.进程与线程 1.进程 2.线程 3.进程与线程的区别 4.Python GIL 5.thread模块 6.Join与Daemon 7.线程锁(Mut ...

  4. 12.2 关闭DLM 自动收集统计信息 (SCM0)ORA-00600之[ksliwat: bad wait time]

    一.报错日志 db_alert ORA-: ??????, ??: [ksliwat: bad wait time], [], [], [], [], [], [], [], [], [], [], ...

  5. SPI有关CPOL和CPHA的时序图

    SPI模块为了和外设进行数据交换,根据外设工作要求,其输出串行同步时钟极性和相位可以进行配置. 时钟极性(CPOL)对传输协议没有重大的影响. 如果CPOL=0,串行同步时钟的空闲状态为低电平: 如果 ...

  6. [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 ...

  7. 20155219实验三 敏捷开发与XP实践

    实验内容 XP基础 XP核心实践 相关工具 敏捷开发与XP 1.敏捷开发(Agile Development)是一种以人为核心.迭代.循序渐进的开发方法."敏捷流程"是一系列价值观 ...

  8. SQLI DUMB SERIES-6

    less6 输入 ?id=1" 说明双引号未被过滤,输入的id被一对双引号所包围,存在注入点,可以闭合双引号. 而输入正常时 情况和less5相同,因此注入同less5.

  9. alpha冲刺(1/10)(作废)

    前言 队名:旅法师 作业链接 队长博客 燃尽图 会议 站立式会议照片 会议内容 陈晓彬(组长) 昨日进展: 召开会议 安排任务 博客撰写 问题困扰: 没有做项目经理的经验,在沟通方面专业知识不够. 心 ...

  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