如何锻炼分析问题的方法?请各位大虾指教~~

来源:互联网 发布:手机质量检测软件 编辑:程序博客网 时间:2024/04/24 19:42

最近在solaris下移植heartbeat模块,遇到了一个问题,就是连接其他节点的crm应用程序,有时出现连接失败的问题。

有时返回return -5,有时return-6

代码如下:

#include <stdio.h>#include <string.h>#include <stdlib.h>#include <unistd.h>#include <sys/socket.h>#include <sys/ioctl.h>#include <sys/sockio.h>#include <net/if.h>    //struct ifconf 在这里面声明#include <netinet/in.h>#include <inttypes.h>#include <arpa/inet.h> #include <fcntl.h>#include <errno.h>#define CRMPORT 3387#ifndef SOCKET#define SOCKET int#endif#ifndef SOCKET_ERROR#define SOCKET_ERROR (-1)#endif#ifndef INVALID_SOCKET#define INVALID_SOCKET 0#endif//连接指定ip和端口8003,若连接成功,则返回1,否则返回0int checkConnectToIp(const char *ipStr){int sockfd;struct sockaddr_in my_addr;struct timeval timeval_time_out;int ul = 1;memset(&(my_addr), 0, sizeof(my_addr));/* zero my address struct */my_addr.sin_family = AF_INET;/* host byte order */my_addr.sin_port = htons((u_short)CRMPORT);my_addr.sin_addr.s_addr = inet_addr(ipStr); if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET) {int i = 0;fprintf(stdout, "checkConnectToIp: socket error-%d!\n",i);return(sockfd);}//增加设置超时时间,超时时间设置为500ms//初始化超时时间memset(&timeval_time_out, 0, sizeof(struct timeval));timeval_time_out.tv_sec= 0;//l_sec为超时时间,秒timeval_time_out.tv_usec= 500;//l_usec是毫秒// 设置超时时间,成功返回0/*if (0!=setsockopt(sockfd, SOL_SOCKET, SO_SNDTIMEO, &timeval_time_out, sizeof(struct timeval))){if (0 != closesocket(sockfd))return 0;}*/// 设置socket为非阻塞模式int flag;flag = fcntl(sockfd,F_GETFL,0);flag |= O_NONBLOCK;fcntl(sockfd,F_SETFL,flag);//设置非阻塞char* errMsg;if (connect(sockfd, (struct sockaddr *) &my_addr, sizeof(struct sockaddr_in)) == 0){close(sockfd);return 1;}else{perror("socket connect");if (errno == EINPROGRESS){printf("connect EINPROGRESS\n");}fd_set fd_set_write;int optval=0;int optlen=sizeof(int);int selectrt = 0;FD_ZERO(&fd_set_write);FD_SET(sockfd, &fd_set_write);selectrt = select(sockfd + 1, NULL, &fd_set_write, NULL, &timeval_time_out);printf("selectrt---%d\n",selectrt);if ( 0 < selectrt){if ( 0!=getsockopt(sockfd, SOL_SOCKET, SO_ERROR, &optval, &optlen) ){FD_CLR(sockfd, &fd_set_write);close(sockfd);printf("checkConnectToIp:return -4\n");return -4;}printf("optval:%d\n",optval);if (0!=optval){FD_CLR(sockfd, &fd_set_write);close(sockfd);printf("checkConnectToIp:return -5\n");return -5;}FD_CLR(sockfd, &fd_set_write);}else{FD_CLR(sockfd, &fd_set_write);close(sockfd);printf("checkConnectToIp:return -6\n");return -6;}close(sockfd);return 1;}}int main(){int ret = 0;ret = checkConnectToIp("10.151.12.122");  //连对方ipprintf("checkConnectToIp ret ------ %d\n",ret);getchar();return 0;}


 先说下我的思路:

1、通过对方ip和端口,与对方进行connect连接。

2、如果能connect成功,则直接return 1。

3、否则,调用select机制进行连接,如果select超时,则return -6;如果通过select机制,有描述符发生变化,即select返回值大于0,则通过getsockopt判断其SO_ERROR状态,如果SO_ERROR返回值为0,则return 1,否则 return -5。

 

我遇到的问题和在老大的批评+指导下的分析解决方法为:

1、弄了一个对方ip作为服务端的程序,结果总是return -5。 于是查看服务端代码,一看不是tcp socket,用的是udp socket,哎,图省事不行呀!!! 经改正,代码select返回值为1,测试程序return 1。

2、于是放到大环境中startHB去跑,结果连对端节点的crm,有时返回-6,有时返回1。老大看了看,想可能是select函数在solaris平台和windows平台的用法不一样,于是到google里搜索“openindiana man select return”,发现返回值说明如下:

      If the timeout argument is a null pointer, select() blocks until an  event
       causes  one  of the masks to be returned with a valid (non-zero) value.
       If the time limit expires before any event occurs that would cause  one
       of the masks to be set to a non-zero value, select() completes success-
       fully and returns 0.

     RETURN VALUES
       On  successful completion, select() and pselect() return the total num-
       ber of bits set in the bit masks.
Otherwise, -1 is returned  and  errno
       is set to indicate the error.

       The  FD_CLR(),  FD_SET(),  and  FD_ZERO()  macros return no value.  The
       FD_ISSET() macro returns a non-zero value  if  the  bit for  the  file
       descriptor  fd  is  set in the file descriptor set pointed to by fdset,
       and 0 otherwise.
   

     意思就是:(1)在超时时间内,有事件发生的话,返回非0值,返回值为多少位被置位了。(2)超时时间到了,select成功执行并且返回值为0。(3)返回-1表示函数出错。

     那说明该程序在select的用法上没有错。

3、进一步分析:由于有时返回-6,说明走的是超时的流程。老大说:超时?那是不是时间设置的不对?下面现将超时时间由原来的500毫秒改成1秒试试;再不行再改成2秒;如果还不可以,说明不是时间量的问题,看看事件设置上是不是有区别,有问题。将程序超时时间500毫秒改成1秒后,经大环境测试可以,反复测试10次以上没问题。

很多时候我在努力并坚持去解决问题,但是效果不理想,关键在于“方法”,各位大虾都很有经验,可不可以告诉我该如何锻炼分析问题的方法?除了亲身经历外,有没有什么书籍或杂志,论坛值得推荐?谢谢各位啦~~~~~~

原创粉丝点击