gsoap:实现线程池处理时获取到客户端的ip

问题:

在使用线程池处理客户端请求时发现不能获取到客户端的ip!

原因:

由于在server_loop注循环中只把连接字sock加到queue队列中,并没有客户端IP,所以每一次queue回调函数只能取得sock连接字,没有客户端的ip

解决方法:

在将sock加入queue队列的同时把ip也加入到ips队列中,ips队列的长度和queue相同,而且存的数据下标要相同,取sock处理时也把IP取出来,即可得到了客户端IP

步骤:

定义全局保存IP地址的变量

[cpp] view plaincopyprint?

  1. static unsigned long ips[MAX_QUEUE];
    static unsigned long ips[MAX_QUEUE];

修改 enqueue函数

[cpp] view plaincopyprint?

  1. int enqueue(SOAP_SOCKET sock,unsigned long ip)//添加ip的参数
  2. {
  3. int status = SOAP_OK;
  4. int next;
  5. int ret;
  6. if ((ret = MUTEX_LOCK(queue_cs)))
  7. fprintf(stderr, "MUTEX_LOCK error %d\n", ret);
  8. next = (tail + 1) % MAX_QUEUE;  //1000
  9. if (head == next)
  10. {
  11. /* don‘t block on full queue,
  12. * 队列已满,return SOAP_EOM */
  13. status = SOAP_EOM;
  14. }
  15. else
  16. {
  17. queue[tail] = sock;
  18. ips[tail] = ip;  //保存ip
  19. tail = next;
  20. if ((ret = COND_SIGNAL(queue_cv)))
  21. fprintf(stderr, "COND_SIGNAL error %d\n", ret);
  22. }
  23. if ((ret = MUTEX_UNLOCK(queue_cs)))
  24. fprintf(stderr, "MUTEX_UNLOCK error %d\n", ret);
  25. return status;
  26. }
int enqueue(SOAP_SOCKET sock,unsigned long ip)//添加ip的参数
{
        int status = SOAP_OK;
        int next;
        int ret;
        if ((ret = MUTEX_LOCK(queue_cs)))
                fprintf(stderr, "MUTEX_LOCK error %d\n", ret);
        next = (tail + 1) % MAX_QUEUE;  //1000
        if (head == next)
        {
                /* don't block on full queue,
                 * 队列已满,return SOAP_EOM */
                status = SOAP_EOM;
        }
        else
        {
                queue[tail] = sock;
                ips[tail] = ip;  //保存ip
                tail = next;
                if ((ret = COND_SIGNAL(queue_cv)))
                        fprintf(stderr, "COND_SIGNAL error %d\n", ret);
        }
        if ((ret = MUTEX_UNLOCK(queue_cs)))
                fprintf(stderr, "MUTEX_UNLOCK error %d\n", ret);
        return status;
}

添加dequeue_ip()函数

[cpp] view plaincopyprint?

  1. unsigned long  dequeue_ip()
  2. {
  3. unsigned long ip;
  4. int num=0;
  5. if(head == 0)
  6. num = MAX_QUEUE - 1;
  7. else
  8. num = head -1;
  9. ip = ips[num];
  10. return ip;
  11. }
unsigned long  dequeue_ip()
{
        unsigned long ip;
        int num=0;
        if(head == 0)
            num = MAX_QUEUE - 1;
        else
            num = head -1;
        ip = ips[num];
        return ip;
}

修改queue回调函数函数

[cpp] view plaincopyprint?

  1. void *process_queue(void *soap)
  2. {
  3. struct soap *tsoap = (struct soap*)soap;
  4. for (;;)
  5. {
  6. tsoap->socket = dequeue();
  7. tsoap->ip = dequeue_ip();//获取相应的ip地址
  8. if (!soap_valid_socket(tsoap->socket))
  9. {
  10. #ifdef DEBUG
  11. fprintf(stderr, "Thread %d terminating\n", (int)(long)tsoap->user);
  12. #endif
  13. break;
  14. }
void *process_queue(void *soap)
{
        struct soap *tsoap = (struct soap*)soap;
        for (;;)
        {
                tsoap->socket = dequeue();
                tsoap->ip = dequeue_ip();//获取相应的ip地址
                if (!soap_valid_socket(tsoap->socket))
                {
#ifdef DEBUG
                        fprintf(stderr, "Thread %d terminating\n", (int)(long)tsoap->user);
#endif
                        break;
                }

解决!

测试:

在http_get_handler函数中测试

[cpp] view plaincopyprint?

</pre><div class="dp-highlighter bg_cpp"><div class="bar"><div class="tools"><strong>[cpp]</strong> <a target=_blank class="ViewSource" title="view plain" href="http://blog.csdn.net/jk110333/article/details/9445761#">view plain</a><a target=_blank class="CopyToClipboard" title="copy" href="http://blog.csdn.net/jk110333/article/details/9445761#">copy</a><a target=_blank class="PrintSource" title="print" href="http://blog.csdn.net/jk110333/article/details/9445761#">print</a><a target=_blank class="About" title="?" href="http://blog.csdn.net/jk110333/article/details/9445761#">?</a></div></div><ol class="dp-cpp"><li class="alt"><span class="datatypes">int</span> http_get_handler(<span class="keyword">struct</span> soap *soap)  </li><li>{  </li><li class="alt">    。。。。。  </li><li>     fprintf(stderr, <span class="string">"Request accepts connection from IP %d.%d.%d.%d\n"</span>,  </li><li class="alt">           (<span class="datatypes">int</span>)(soap->ip>>24)&0xFF, (<span class="datatypes">int</span>)(soap->ip>>16)&0xFF,(<span class="datatypes">int</span>) (soap->ip>>8)&0xFF, (<span class="datatypes">int</span>)soap->ip&0xFF);  </li><li>。。。。。。  </li><li class="alt">}  </li></ol></div><pre style="DISPLAY: none" class="cpp" name="code">int http_get_handler(struct soap *soap)
{
    。。。。。
     fprintf(stderr, "Request accepts connection from IP %d.%d.%d.%d\n",
           (int)(soap->ip>>24)&0xFF, (int)(soap->ip>>16)&0xFF,(int) (soap->ip>>8)&0xFF, (int)soap->ip&0xFF);
。。。。。。
}

输出:

[ruby] view plaincopyprint?

  1. Request accepts connection from IP 192.168.1.136
  2. Request accepts connection from IP 192.168.1.136
  3. Thread 3 finished serving request with failure 404
  4. Error 404 fault: SOAP-ENV:Client [no subcode]
  5. "HTTP Error: 404 Not Found"
  6. Detail: [no detail]
  7. Request accepts connection from IP 192.168.1.87
  8. Request accepts connection from IP 192.168.1.87
  9. Request accepts connection from IP 192.168.1.87
时间: 2024-08-12 04:08:48

gsoap:实现线程池处理时获取到客户端的ip的相关文章

怎么使用PHP获取用户客户端真实IP的解决方案呢?

function getIp(){if (getenv("HTTP_CLIENT_IP") && strcasecmp(getenv("HTTP_CLIENT_IP"), "unknown"))$ip = getenv("HTTP_CLIENT_IP");else if (getenv("HTTP_X_FORWARDED_FOR") && strcasecmp(getenv(

PHP获取APP客户端的IP地址的方法

分析php获取客户端ip 用php能获取客户端ip,这个大家都知道,代码如下: [php] view plaincopyprint? /** * 获取客户端ip * @param number $type * @return string */ function getClientIp($type = 0) { $type       =  $type ? 1 : 0; static $ip  =   NULL; if ($ip !== NULL) return $ip[$type]; if (

php获取window客户端物理IP地址信息

<?php $info=system("ipconfig /all"); $contents=ob_get_clean(); $contents=iconv('GBK', 'UTF-8', $contents); $contents=explode("\r\n",$contents); foreach($contents as $k=>$v) { $v=trim($v); if(strpos($v,"物理地址")!==false) {

Java多线程系列--“JUC线程池”03之 线程池原理(二)

线程池示例 在分析线程池之前,先看一个简单的线程池示例. import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; public class ThreadPoolDemo1 { public static void main(String[] args) { // 创建一个可重用固定线程数的线程池 ExecutorService pool = Executors.newFixedThre

java多线程系类:JUC线程池:03之线程池原理(二)(转)

概要 在前面一章"Java多线程系列--"JUC线程池"02之 线程池原理(一)"中介绍了线程池的数据结构,本章会通过分析线程池的源码,对线程池进行说明.内容包括:线程池示例参考代码(基于JDK1.7.0_40)线程池源码分析(一) 创建"线程池"(二) 添加任务到"线程池"(三) 关闭"线程池" 转载请注明出处:http://www.cnblogs.com/skywang12345/p/3509954.h

转:【Java并发编程】之十九:并发新特性—Executor框架与线程池(含代码)

  Executor框架简介 在Java5之后,并发编程引入了一堆新的启动.调度和管理线程的API.Executor框架便是Java 5中引入的,其内部使用了线程池机制,它在java.util.cocurrent 包下,通过该框架来控制线程的启动.执行和关闭,可以简化并发编程的操作.因此,在Java 5之后,通过Executor来启动线程比使用Thread的start方法更好,除了更易管理,效率更好(用线程池实现,节约开销)外,还有关键的一点:有助于避免this逃逸问题--如果我们在构造器中启动

Java线程池使用和分析(二) - execute()原理

相关文章目录: Java线程池使用和分析(一) Java线程池使用和分析(二) - execute()原理 execute()是 java.util.concurrent.Executor接口中唯一的方法,JDK注释中的描述是“在未来的某一时刻执行命令command”,即向线程池中提交任务,在未来某个时刻执行,提交的任务必须实现Runnable接口,该提交方式不能获取返回值.下面是对execute()方法内部原理的分析,分析前先简单介绍线程池有哪些状态,在一系列执行过程中涉及线程池状态相关的判断

MySQL具体解释(8)----------MySQL线程池总结(二)

这篇文章是对上篇文章的一个补充,主要环绕下面两点展开.one-connection-per-thread的实现方式以及线程池中epoll的使用. one-connection-per-thread 依据scheduler_functions的模板,我们也能够列出one-connection-per-thread方式的几个关键函数. static scheduler_functions con_per_functions= { max_connection+1, // max_threads NU

基于线程池的线程调度管控系统

本文将详细描述"基于线程池的线程调度管控系统"的实现原理,以梳理当时的编程思路. 简单叙述一下此线程池的开发背景:客户端是批量运行的,虽然客户端均运行在服务器上,但是大量客户端运行时它们对机器资源是抢占式的,所以客户端在大规模运行时与单次运行时的运行效果是不一样的,因为相同客户端在单次运行与大规模运行时所占有的资源量是不同的,理论上说大规模运行时客户端的数量越多,每个客户端所占有的资源量就越少,于是我们认为解决问题的关键应该是不管是单次运行还是大规模运行,相同客户端所获取的资源量就应该