一、问题描写叙述

如今以C/S架构为例。client向server端发送要查找的数字,server端启动线程中的线程进行对应的查询。将查询结果显示出来。

二、实现方案

1. 整个project以client、server、lib组织。例如以下图所看到的:

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3poaWNoZW5nMTk4Mw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

2. 进入lib。

socket.h、socket.c

  1. /**
  2. @file socket.h
  3. @brief Socket API header file
  4.  
  5. TCP socket utility functions, it provides simple functions that helps
  6. to build TCP client/server.
  7.  
  8. @author wangzhicheng
  9. */
  10. #ifndef SOCKET_H
  11. #define SOCKET_H
  12.  
  13. #include <stdio.h>
  14. #include <stdlib.h>
  15. #include <string.h>
  16. #include <errno.h>
  17. #include <sys/socket.h>
  18. #include <sys/types.h>
  19. #include <resolv.h>
  20. #include <fcntl.h>
  21.  
  22. #define MAX_CONNECTION 20
  23.  
  24. int TCPServerInit(int port, int *serverfd);
  25. int TCPServerWaitConnection(int serverfd, int *clientfd, char *clientaddr);
  26. int TCPServerSelect(int* serverfdlist, int num, int *clientfd, char *clientaddr);
  27. int TCPClientInit(int *clientfd);
  28. int TCPClientConnect(const int clientfd, const char *addr, int port);
  29. int TCPNonBlockRead(int clientfd, char* buf, int size);
  30. int TCPBlockRead(int clientfd, char* buf, int size);
  31. int TCPWrite(int clientfd, char* buf, int size);
  32. void TCPClientClose(int sockfd);
  33. void TCPServerClose(int sockfd);
  34.  
  35. #endif

socket.c

  1. #include "socket.h"
  2. /*
  3. * @brief initialize TCP server
  4. * @port port number for socket
  5. * @serverfd server socket fd
  6. * return server socked fd for success, on error return error code
  7. * */
  8. int TCPServerInit(int port, int *serverfd) {
  9. struct sockaddr_in dest;
  10. // create socket , same as client
  11. *serverfd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
  12. if(*serverfd < 0) return -1;
  13. /// initialize structure dest
  14. memset((void*)&dest, '\0', sizeof(dest));
  15. dest.sin_family = PF_INET;
  16. dest.sin_port = htons(port);
  17. dest.sin_addr.s_addr = INADDR_ANY;
  18. // Assign a port number to socket
  19. bind( *serverfd, (struct sockaddr*)&dest, sizeof(dest));
  20.  
  21. return *serverfd;
  22. }
  23. /*
  24. * @brief wait client connect
  25. * @serverfd server socket fd
  26. * @clientfd client socket fd
  27. * @clientaddr client address which connect to server
  28. * return client fd, on error return error code
  29. * */
  30. int TCPServerWaitConnection(int serverfd, int *clientfd, char *clientaddr) {
  31. struct sockaddr_in client_addr;
  32. socklen_t addrlen = sizeof(client_addr);
  33. // make it listen to socket
  34. listen( serverfd, 20);
  35. // Wait and Accept connection
  36. *clientfd = accept(serverfd, (struct sockaddr*)&client_addr, &addrlen);
  37. strcpy( clientaddr, (const char *)( inet_ntoa( client_addr.sin_addr)));
  38.  
  39. return *clientfd;
  40. }
  41. /*
  42. * @brief initialize TCP client
  43. * @clientfd client socket fd
  44. * return client socked fd for success, on error return error code
  45. */
  46. int TCPClientInit(int *clientfd) {
  47. *clientfd = socket(PF_INET, SOCK_STREAM, 0);
  48.  
  49. return *clientfd;
  50. }
  51. /*
  52. * @brief connect to TCP server
  53. * @clientfd client socket fd
  54. * @addr server address
  55. * @port server port number
  56. * return 0 for success, on error -1 is returned
  57. */
  58. int TCPClientConnect(const int clientfd, const char *addr, int port) {
  59. struct sockaddr_in dest;
  60. // initialize value in dest
  61. memset(&dest, '\0', sizeof(dest));
  62. dest.sin_family = PF_INET;
  63. dest.sin_port = htons(port);
  64. inet_aton(addr, &dest.sin_addr);
  65.  
  66. // Connecting to server
  67. return connect(clientfd, (struct sockaddr*)&dest, sizeof(dest));
  68. }
  69. /*
  70. * @brief non-block read from TCP socket
  71. * @clientfd socket fd
  72. * @buf input buffer
  73. * @size buffer size
  74. * return the length of read data
  75. */
  76. int TCPNonBlockRead(int clientfd, char* buf, int size) {
  77. int opts;
  78. opts = fcntl(clientfd, F_GETFL);
  79. opts = (opts | O_NONBLOCK);
  80. fcntl(clientfd, F_SETFL, opts);
  81.  
  82. return recv(clientfd, buf, size, 0);
  83. }
  84. /*
  85. * @brief block read from TCP socket
  86. * @clientfd socket fd
  87. * @buf input buffer
  88. * @size buf size
  89. * return the length of read data
  90. */
  91. int TCPBlockRead(int clientfd, char* buf, int size) {
  92. int opts;
  93. opts = fcntl(clientfd, F_GETFL);
  94. opts = (opts & ~O_NONBLOCK);
  95. fcntl(clientfd, F_SETFL, opts);
  96.  
  97. return recv(clientfd, buf, size, 0);
  98. }
  99. /*
  100. * @brief write to TCP socket
  101. * @clientfd socket fd
  102. * @buf output buf
  103. * @size output buf length
  104. * return the length of the actual written data, -1: disconnected
  105. */
  106. int TCPWrite(int clientfd, char* buf, int size) {
  107. int len= 0;
  108. /* set socket to nonblock */
  109. int ret = fcntl(clientfd, F_GETFL);
  110. ret |= O_NONBLOCK;
  111. if (fcntl(clientfd, F_SETFL, ret) < 0 ) {
  112. printf("set socket to nonblock fail [%d] !\n", errno);
  113. }
  114. len = send(clientfd, buf, size, MSG_NOSIGNAL);
  115.  
  116. return len;
  117. }
  118. /*
  119. * @brief close the tcp connection
  120. * @sockfd socket fd
  121. * return none
  122. */
  123. void TCPConnectionClose(int sockfd) {
  124. close(sockfd);
  125. }

threadpool.h

  1. #ifndef THREADPOOL_H
  2. #define THREADPOOL_H
  3.  
  4. #include <stdio.h>
  5. #include <stdlib.h>
  6. #include <pthread.h>
  7. #include <unistd.h>
  8. struct job
  9. {
  10. void* (*callback_function)(void *arg); //线程回调函数
  11. void *arg; //回调函数參数
  12. struct job *next;
  13. };
  14.  
  15. struct threadpool
  16. {
  17. int thread_num; //线程池中开启线程的个数
  18. int queue_max_num; //队列中最大job的个数
  19. struct job *head; //指向job的头指针
  20. struct job *tail; //指向job的尾指针
  21. pthread_t *pthreads; //线程池中全部线程的pthread_t
  22. pthread_mutex_t mutex; //相互排斥信号量
  23. pthread_cond_t queue_empty; //队列为空的条件变量
  24. pthread_cond_t queue_not_empty; //队列不为空的条件变量
  25. pthread_cond_t queue_not_full; //队列不为满的条件变量
  26. int queue_cur_num; //队列当前的job个数
  27. int queue_close; //队列是否已经关闭
  28. int pool_close; //线程池是否已经关闭
  29. };
  30.  
  31. //================================================================================================
  32. //函数名: threadpool_init
  33. //函数描写叙述: 初始化线程池
  34. //输入: [in] thread_num 线程池开启的线程个数
  35. // [in] queue_max_num 队列的最大job个数
  36. //输出: 无
  37. //返回: 成功:线程池地址 失败:NULL
  38. //================================================================================================
  39. struct threadpool* threadpool_init(int thread_num, int queue_max_num);
  40.  
  41. //================================================================================================
  42. //函数名: threadpool_add_job
  43. //函数描写叙述: 向线程池中加入任务
  44. //输入: [in] pool 线程池地址
  45. // [in] callback_function 回调函数
  46. // [in] arg 回调函数參数
  47. //输出: 无
  48. //返回: 成功:0 失败:-1
  49. //================================================================================================
  50. int threadpool_add_job(struct threadpool *pool, void* (*callback_function)(void *arg), void *arg);
  51.  
  52. //================================================================================================
  53. //函数名: threadpool_destroy
  54. //函数描写叙述: 销毁线程池
  55. //输入: [in] pool 线程池地址
  56. //输出: 无
  57. //返回: 成功:0 失败:-1
  58. //================================================================================================
  59. int threadpool_destroy(struct threadpool *pool);
  60.  
  61. //================================================================================================
  62. //函数名: threadpool_function
  63. //函数描写叙述: 线程池中线程函数
  64. //输入: [in] arg 线程池地址
  65. //输出: 无
  66. //返回: 无
  67. //================================================================================================
  68. void* threadpool_function(void* arg);
  69. #endif

threadpool.c

  1. #include "threadpool.h"
  2.  
  3. struct threadpool* threadpool_init(int thread_num, int queue_max_num) {
  4. struct threadpool *pool = NULL;
  5. do
  6. {
  7. pool = malloc(sizeof(struct threadpool));
  8. if (NULL == pool)
  9. {
  10. printf("failed to malloc threadpool!\n");
  11. break;
  12. }
  13. pool->thread_num = thread_num;
  14. pool->queue_max_num = queue_max_num;
  15. pool->queue_cur_num = 0;
  16. pool->head = NULL;
  17. pool->tail = NULL;
  18. if (pthread_mutex_init(&(pool->mutex), NULL))
  19. {
  20. printf("failed to init mutex!\n");
  21. break;
  22. }
  23. if (pthread_cond_init(&(pool->queue_empty), NULL))
  24. {
  25. printf("failed to init queue_empty!\n");
  26. break;
  27. }
  28. if (pthread_cond_init(&(pool->queue_not_empty), NULL))
  29. {
  30. printf("failed to init queue_not_empty!\n");
  31. break;
  32. }
  33. if (pthread_cond_init(&(pool->queue_not_full), NULL))
  34. {
  35. printf("failed to init queue_not_full!\n");
  36. break;
  37. }
  38. pool->pthreads = malloc(sizeof(pthread_t) * thread_num);
  39. if (NULL == pool->pthreads)
  40. {
  41. printf("failed to malloc pthreads!\n");
  42. break;
  43. }
  44. pool->queue_close = 0;
  45. pool->pool_close = 0;
  46. int i;
  47. for (i = 0; i < pool->thread_num; ++i)
  48. {
  49. pthread_create(&(pool->pthreads[i]), NULL, threadpool_function, (void *)pool);
  50. }
  51.  
  52. return pool;
  53. } while (0);
  54.  
  55. return NULL;
  56. }
  57. int threadpool_add_job(struct threadpool* pool, void* (*callback_function)(void *arg), void *arg) {
  58. if(pool == NULL || callback_function == NULL || arg == NULL) return -1;
  59.  
  60. pthread_mutex_lock(&(pool->mutex));
  61. while ((pool->queue_cur_num == pool->queue_max_num) && !(pool->queue_close || pool->pool_close))
  62. {
  63. pthread_cond_wait(&(pool->queue_not_full), &(pool->mutex)); //队列满的时候就等待
  64. }
  65. if (pool->queue_close || pool->pool_close) //队列关闭或者线程池关闭就退出
  66. {
  67. pthread_mutex_unlock(&(pool->mutex));
  68. return -1;
  69. }
  70. struct job *pjob =(struct job*) malloc(sizeof(struct job));
  71. if (NULL == pjob)
  72. {
  73. pthread_mutex_unlock(&(pool->mutex));
  74. return -1;
  75. }
  76. pjob->callback_function = callback_function;
  77. pjob->arg = arg;
  78. pjob->next = NULL;
  79. if (pool->head == NULL)
  80. {
  81. pool->head = pool->tail = pjob;
  82. pthread_cond_broadcast(&(pool->queue_not_empty)); //队列空的时候,有任务来时就通知线程池中的线程:队列非空
  83. }
  84. else
  85. {
  86. pool->tail->next = pjob;
  87. pool->tail = pjob;
  88. }
  89. pool->queue_cur_num++;
  90. pthread_mutex_unlock(&(pool->mutex));
  91. return 0;
  92. }
  93.  
  94. void* threadpool_function(void* arg) {
  95. struct threadpool *pool = (struct threadpool*)arg;
  96. struct job *pjob = NULL;
  97. while (1) //死循环
  98. {
  99. pthread_mutex_lock(&(pool->mutex));
  100. while ((pool->queue_cur_num == 0) && !pool->pool_close) //队列为空时,就等待队列非空
  101. {
  102. pthread_cond_wait(&(pool->queue_not_empty), &(pool->mutex));
  103. }
  104. if (pool->pool_close) //线程池关闭,线程就退出
  105. {
  106. pthread_mutex_unlock(&(pool->mutex));
  107. pthread_exit(NULL);
  108. }
  109. pool->queue_cur_num--;
  110. pjob = pool->head;
  111. if (pool->queue_cur_num == 0)
  112. {
  113. pool->head = pool->tail = NULL;
  114. }
  115. else
  116. {
  117. pool->head = pjob->next;
  118. }
  119. if (pool->queue_cur_num == 0)
  120. {
  121. pthread_cond_signal(&(pool->queue_empty)); //队列为空,就能够通知threadpool_destroy函数,销毁线程函数
  122. }
  123. if (pool->queue_cur_num == pool->queue_max_num - 1)
  124. {
  125. pthread_cond_broadcast(&(pool->queue_not_full)); //队列非满。就能够通知threadpool_add_job函数,加入新任务
  126. }
  127. pthread_mutex_unlock(&(pool->mutex));
  128.  
  129. (*(pjob->callback_function))(pjob->arg); //线程真正要做的工作,回调函数的调用
  130. free(pjob);
  131. pjob = NULL;
  132. }
  133. }
  134. int threadpool_destroy(struct threadpool *pool) {
  135. if(pool == NULL) return -1;
  136. pthread_mutex_lock(&(pool->mutex));
  137. if (pool->queue_close || pool->pool_close) //线程池已经退出了,就直接返回
  138. {
  139. pthread_mutex_unlock(&(pool->mutex));
  140. return -1;
  141. }
  142.  
  143. pool->queue_close = 1; //置队列关闭标志
  144. while (pool->queue_cur_num != 0)
  145. {
  146. pthread_cond_wait(&(pool->queue_empty), &(pool->mutex)); //等待队列为空
  147. }
  148.  
  149. pool->pool_close = 1; //置线程池关闭标志
  150. pthread_mutex_unlock(&(pool->mutex));
  151. pthread_cond_broadcast(&(pool->queue_not_empty)); //唤醒线程池中正在堵塞的线程
  152. pthread_cond_broadcast(&(pool->queue_not_full)); //唤醒加入任务的threadpool_add_job函数
  153. int i;
  154. for (i = 0; i < pool->thread_num; ++i)
  155. {
  156. pthread_join(pool->pthreads[i], NULL); //等待线程池的全部线程运行完成
  157. }
  158.  
  159. pthread_mutex_destroy(&(pool->mutex)); //清理资源
  160. pthread_cond_destroy(&(pool->queue_empty));
  161. pthread_cond_destroy(&(pool->queue_not_empty));
  162. pthread_cond_destroy(&(pool->queue_not_full));
  163. free(pool->pthreads);
  164. struct job *p;
  165. while (pool->head != NULL)
  166. {
  167. p = pool->head;
  168. pool->head = p->next;
  169. free(p);
  170. }
  171. free(pool);
  172. return 0;
  173. }

3.进入client

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3poaWNoZW5nMTk4Mw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

client.c

  1. /*************************************************************************
  2. > File Name: test.c
  3. > Author: wangzhicheng
  4. > Mail: 2363702560@qq.com
  5. > Created Time: Fri 03 Oct 2014 09:43:59 PM WST
  6. ************************************************************************/
  7.  
  8. #include "socket.h"
  9. const char * serveraddr = "127.0.0.1";
  10. #define TCPPORT 4001
  11. int main() {
  12. int clientfd = -1;
  13. char buf[256];
  14. strcpy(buf, "1");
  15. if(TCPClientInit(&clientfd) < 0) {
  16. perror("client init failed...!\n");
  17. exit(EXIT_FAILURE);
  18. }
  19. if(TCPClientConnect(clientfd, serveraddr, TCPPORT)) {
  20. perror("can not connect to server...!\n");
  21. exit(EXIT_FAILURE);
  22. }
  23. if(TCPWrite(clientfd, buf, strlen(buf) == 1)) {
  24. printf("send successfully...!\n");
  25. }
  26. else printf("send failed...!\n");
  27.  
  28. return 0;
  29. }

Makefile

  1. CC=gcc
  2. LIBRARY=../lib
  3. CFLAGS=-I$(LIBRARY)
  4. CXXFLAGS=
  5. OBJS1=client.o socket.o
  6.  
  7. all: client
  8.  
  9. client: $(OBJS1)
  10. $(CC) -o $@ $(OBJS1)
  11.  
  12. socket.o: $(LIBRARY)/socket.c
  13. $(CC) -c $(LIBRARY)/socket.c
  14.  
  15. clean:
  16. rm *.o client > /dev/null 2>&1

4. 进入server

watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvd2FuZ3poaWNoZW5nMTk4Mw==/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">

server.c

  1. /*************************************************************************
  2. > File Name: server.c
  3. > Author: ma6174
  4. > Mail: ma6174@163.com
  5. > Created Time: Sat 04 Oct 2014 09:46:30 PM WST
  6. ************************************************************************/
  7.  
  8. #include "socket.h"
  9. #include "threadpool.h"
  10.  
  11. #define TCPPORT 4001
  12. #define SIZE 256
  13. #define N 10
  14. int array[N] = {1, 2, 6, 8, 12, 88, 208, 222, 688, 1018};
  15. int find(int low, int high, int m) {
  16. int mid;
  17. if(low <= high) {
  18. mid = (low + high) >> 1;
  19. if(array[mid] == m) return 1;
  20. else if(array[mid] > m) return find(low, mid - 1, m);
  21. else return find(mid + 1, high, m);
  22. }
  23. return 0;
  24. }
  25. void* work(void* arg)
  26. {
  27. int *p = (int *) arg;
  28. int m = *p;
  29. if(find(0, N - 1, m)) printf("%d has been found...!\n", m);
  30. else printf("%d has not been found...!\n", m);
  31. sleep(1);
  32. }
  33. int main() {
  34. int serverfd = -1, clientfd = -1;
  35. char clientaddr[SIZE];
  36. char buf[SIZE];
  37. int num;
  38. struct threadpool *pool = NULL;
  39. TCPServerInit(TCPPORT, &serverfd);
  40. if(serverfd < 0) {
  41. perror("server init failed...!\n");
  42. exit(EXIT_FAILURE);
  43. }
  44. pool = threadpool_init(10, 20);
  45. while(1) {
  46. TCPServerWaitConnection(serverfd, &clientfd, clientaddr);
  47. if(clientfd < 0) {
  48. perror("can not connect the clients...!\n");
  49. exit(EXIT_FAILURE);
  50. }
  51. if(TCPBlockRead(clientfd, buf, SIZE) <= 0) {
  52. perror("can not read from client...!\n");
  53. sleep(1);
  54. }
  55. else {
  56. num = atoi(buf);
  57. threadpool_add_job(pool, work, &num);
  58. }
  59. }
  60. threadpool_destroy(pool);
  61.  
  62. return 0;
  63. }

Makefile

  1. CC=gcc
  2. LIBRARY=../lib
  3. CFLAGS=-I$(LIBRARY)
  4. CXXFLAGS=
  5. OBJS1=server.o socket.o threadpool.o
  6.  
  7. all: server
  8.  
  9. server: $(OBJS1)
  10. $(CC) -o $@ $(OBJS1) -lpthread
  11.  
  12. socket.o: $(LIBRARY)/socket.c
  13. $(CC) -c $(LIBRARY)/socket.c
  14.  
  15. threadpool.o: $(LIBRARY)/threadpool.c
  16. $(CC) -c $(LIBRARY)/threadpool.c
  17. clean:
  18. rm *.o client > /dev/null 2>&1

三、測试

四、有关线程池的说明

当线程池被创建时,线程池中有些“空”的线程。即不运行任务,每当一个任务被增加进来时,任务就被组织成任务队列,线程依照队列队头出。队尾进的原则取出头任务运行。

任务队列中所含任务数必须控制在一个上限内。超过上限时。任务被堵塞。当全部任务被运行完,销毁线程池。

Linux线程池在server上简单应用的更多相关文章

  1. 非常精简的Linux线程池实现(一)——使用互斥锁和条件变量

    线程池的含义跟它的名字一样,就是一个由许多线程组成的池子. 有了线程池,在程序中使用多线程变得简单.我们不用再自己去操心线程的创建.撤销.管理问题,有什么要消耗大量CPU时间的任务通通直接扔到线程池里 ...

  2. python线程池ThreadPoolExecutor(上)(38)

    在前面的文章中我们已经介绍了很多关于python线程相关的知识点,比如 线程互斥锁Lock / 线程事件Event / 线程条件变量Condition 等等,而今天给大家讲解的是 线程池ThreadP ...

  3. linux线程池thrmgr源码解析

    linux线程池thrmgr源码解析 1         thrmgr线程池的作用 thrmgr线程池的作用是提高程序的并发处理能力,在多CPU的服务器上运行程序,可以并发执行多个任务. 2      ...

  4. 一个简单的linux线程池(转-wangchenxicool)

    线程池:简单地说,线程池 就是预先创建好一批线程,方便.快速地处理收到的业务.比起传统的到来一个任务,即时创建一个线程来处理,节省了线程的创建和回收的开销,响应更快,效率更高. 在linux中,使用的 ...

  5. Linux下线程池的理解与简单实现

    首先,线程池是什么?顾名思义,就是把一堆开辟好的线程放在一个池子里统一管理,就是一个线程池. 其次,为什么要用线程池,难道来一个请求给它申请一个线程,请求处理完了释放线程不行么?也行,但是如果创建线程 ...

  6. 关于C#线程,线程池和并行运算的简单使用和对比

    转自:https://www.cnblogs.com/jeffwongishandsome/archive/2010/11/12/1876137.html 先大概看一下控制台应用程序的Main方法的主 ...

  7. 【Android】线程池原理及Java简单实现

    线程池简介 多线程技术主要解决处理器单元内多个线程执行的问题,它可以显著减少处理器单元的闲置时间,增加处理器单元的吞吐能力. 假设一个服务器完成一项任务所需时间为: T1 创建线程时间 T2 在线程中 ...

  8. linux线程池

    typedef struct task_node { void *arg; /* fun arg. */ void *(*fun) (void *); /* the real work of the ...

  9. Linux线程池的实现

    线程池的实现 1:自定义封装的条件变量 //condition.h #ifndef _CONDITION_H_ #define _CONDITION_H_ #include <pthread.h ...

随机推荐

  1. drupal 8——在CKEditor中导入video media时添加caption会导致video缩小至消失

    在CKEditor中,我点击media browser,选择video型的media,并在caption中输入video的名字.当我保存后发现在前台页面的video消失了,只留下video的名字,点击 ...

  2. 《Java编程的逻辑》第二部分 面向对象

  3. jQuery——尺寸位置

    获取宽:$(".box").width() 设置宽:$(".box").width(200) 获取高:$(".box").height() ...

  4. JS——dom

    节点的获取 <script> var div = document.getElementById("box");//返回指定标签 var div = document. ...

  5. 3星|《腾讯产业森林:AI时代的创业密码》:后半部分是较详细的创业指南,前面泛泛介绍腾讯、AI

    腾讯产业森林:AI时代的创业密码 前半部分泛泛介绍腾讯对创业者的支持,腾讯支持的创业项目的案例.AI的一些基本介绍,后半部分是比较详细的写给创业者的各阶段行动与选择的指南. 总体评价3星,有一些参考价 ...

  6. 在Windows下安装Elasticsearch5.0

    1.准备工作 安装和配置Java环境 2.下载 地址:https://www.elastic.co/downloads/elasticsearch 老版本:https://www.elastic.co ...

  7. NFS指定端口,NFS缓存(转载)

    nfs服务端: #编辑/etc/nfsmount.conf,在末尾添加: #RQUOTAD_PORT=30001#LOCKD_TCPPORT=30002#LOCKD_UDPPORT=30002#MOU ...

  8. php中fopen不能创建中文文件名文件的问题

    之前网页的chartset用的是utf-8,文件也用utf-8,然后用fopen()创建一个中文文件名的文件时问题就出来了,文件名都是乱 码! 查看了很多文档试了不少方法都解决不了,本来想着用别的方法 ...

  9. 02. 爬取get请求的页面数据

    目录 02. 爬取get请求的页面数据 一.urllib库 二.由易到难的爬虫程序: 02. 爬取get请求的页面数据 一.urllib库 urllib是Python自带的一个用于爬虫的库,其主要作用 ...

  10. opencv图像阈值设置的三种方法

    1.简单阈值设置   像素值高于阈值时,给这个像素赋予一个新值(可能是白色),否则我们给它赋予另外一种颜色(也许是黑色).这个函数就是 cv2.threshhold().这个函数的第一个参数就是原图像 ...