- 论坛徽章:
- 0
|
本帖最后由 liuchang8877 于 2012-08-02 15:47 编辑
弱弱地问下, clien t /server 同时都用select , client 向 server 发数据, 为什么 server 端的 select 的返回值是0?? 必须先从server 端 send 才能建立链接?
希望大牛们指教。
- //server.c
- #include<stdio.h>
- #include<stdlib.h>
- #include<unistd.h>
- #include<sys/socket.h>
- #include<arpa/inet.h>
- #include<sys/types.h>
- #include<errno.h>
- #include<netdb.h>
- #include<string.h>
- #include<signal.h>
- #include<stdarg.h> /*va_list*/
- #define DIRECT_GET_CFG_PORT "21000"
- #define PROTOCOL "tcp"
- #define LINK_CHECK_TIMES 5
- FILE *SafeLibErrorDest = NULL;
- const char *SafeLibErrorLoc;
- int SafeLibErrno = 0;
- int server_init(const char *port,const char *proto);
- void socketaddr_init(struct sockaddr_in *socketaddr);
- int socketaddr_service(struct sockaddr_in *socketaddr,const char *service, const char *proto);
- static int checkstring(const char *string);
- void HandleError(int ecode, const char *const caller,
- const char *fmt, ...);
- int prototype(const char *proto);
- int resolveproto(const char *proto);
- int server_init(const char *port,const char *proto)
- {
- /*debug*/
- printf("server_init,port:%s---proto:%s\n",port,proto);
- struct sockaddr_in socketaddr;
- int mastersock;
- int trueval = 1;
-
- socketaddr_init(&socketaddr);
- socketaddr.sin_addr.s_addr = INADDR_ANY;
- socketaddr_service(&socketaddr,port,proto);
-
- mastersock = socket(PF_INET,prototype(proto),resolveproto(proto));
-
- if(mastersock < 0){
- HandleError(errno,"serverinit","counldn't create socket");
- return -1;
- }
- setsockopt(mastersock,SOL_SOCKET,SO_REUSEADDR,&trueval,sizeof(socklen_t));
- if(bind(mastersock,(struct sockaddr*)&socketaddr,sizeof(socketaddr)) < 0){
- HandleError(errno,"serverinit","couldn't create socket");
- return -1;
- }
-
- if(prototype(proto) == SOCK_STREAM){
- if(listen(mastersock,5) < 0){
- HandleError(errno,"serverinit","listen on port %d failed",port);
- return -1;
- }
- }
- else if(prototype(proto) == SOCK_DGRAM){
- int buf_size = 512 *1024;
- setsockopt(mastersock,SOL_SOCKET,SO_RCVBUF,(char *)&buf_size,sizeof(int));
- }
-
- return mastersock;
- }
- void socketaddr_init(struct sockaddr_in *socketaddr)
- {
- memset(socketaddr,0,sizeof(struct sockaddr));
- socketaddr->sin_family = AF_INET;
- }
- int socketaddr_service(struct sockaddr_in *socketaddr,const char *service, const char *proto)
- {
- struct servent *serviceaddr;
- /*debug*/
- printf("socketaddr_service,service:%s---proto:%s\n",service,proto);
- if(strcmp(service,"0") ==0)
- socketaddr->sin_port = 0;
- else{
- serviceaddr = getservbyname(service,proto);
- if(serviceaddr){
- socketaddr->sin_port = serviceaddr->s_port;
- }else{
- if(checkstring(service)){
- HandleError(0,"socket_service","no lookup for %s/%s",service,proto);
- return -1;
- }
- if(0 == (socketaddr->sin_port = htons((u_short)atoi(service)))){
- HandleError(0,"socketaddr_service","numeric conversion failed");
- return -1;
- }
- }
- }
- /*debug*/
- printf("socketaddr_service:port:%d\n",socketaddr->sin_port);
- return 0;
- }
- static int checkstring(const char *string)
- {
- unsigned int counter;
- for(counter = 0; counter <strlen(string); counter++)
- if(!isdigit(string[counter]))
- return 1;
- return 0;
- }
- void HandleError(int ecode, const char *const caller,
- const char *fmt, ...) {
- va_list fmtargs;
- struct sigaction sastruct;
- FILE *of = (SafeLibErrorDest) ? SafeLibErrorDest : stderr;
- /* Safe these into global variables for any possible signal handler. */
- SafeLibErrorLoc = caller;
- SafeLibErrno = ecode;
- /* Print the error message(s) */
- va_start(fmtargs, fmt);
- fprintf(of, "*** Error in %s: ", caller);
- vfprintf(of, fmt, fmtargs);
- va_end(fmtargs);
- fprintf(of, "\n");
- if (ecode) {
- fprintf(of, "*** Error cause: %s\n", strerror(ecode));
- }
- /* Exit if no signal handler. Otherwise, raise a signal. */
- sigaction(SIGUSR1, NULL, &sastruct);
- if (sastruct.sa_handler != SIG_DFL)
- {
- raise(SIGUSR1);
- }
- // else
- // {
- // exit(254);
- // }
- }
- int prototype(const char *proto)
- {
- if(0 == strcmp(proto,"tcp"))
- return SOCK_STREAM;
- if(0 == strcmp(proto,"udp"))
- return SOCK_DGRAM;
- return -1;
- }
- int resolveproto(const char *proto)
- {
- struct protoent *protocol;
- protocol = getprotobyname(proto);
- if (!protocol)
- {
- HandleError(0, "resolveproto", "getprotobyname failed for %s", proto);
- return -1;
- }
- return protocol->p_proto;
- }
- int main(void)
- {
- int mastersock;
- int workersock;
- struct sockaddr_in socketaddr;
- int addrlen;
- int nfds = 0;
-
- fd_set orig_fdset,fdset;
- int selectVal;
- char logmsg[256];
-
- struct timeval timeOut, tvCurr, tvLimit;
- char BUF[256];
- mastersock = server_init(DIRECT_GET_CFG_PORT,PROTOCOL);
- /*debug*/
- printf("*****mastersock:%d\n",mastersock);
- if(mastersock >= nfds)
- nfds = mastersock + 1;
-
- timeOut.tv_sec =LINK_CHECK_TIMES;
- timeOut.tv_usec = 0;
- FD_ZERO(&orig_fdset);
- FD_SET(mastersock,&orig_fdset);
-
- addrlen = sizeof(socketaddr);
- /*debbug*/
- printf("addrlen:%d\n",addrlen);
- gettimeofday(&tvCurr,0);
- tvLimit = tvCurr;
- tvLimit.tv_sec += LINK_CHECK_TIMES;
-
- while(1){
- bcopy(&orig_fdset,&fdset,sizeof(orig_fdset));
- timeOut.tv_sec = tvLimit.tv_sec - tvCurr.tv_sec;
- timeOut.tv_usec = 0;
-
- selectVal = select(nfds,&fdset,(fd_set *)0,(fd_set *)0,0);
- /*debug*/
- printf("selectVal:%d\n",selectVal);
- if(selectVal > 0){
- if(FD_ISSET(mastersock,&fdset)){
- /*debug*/
- printf("Under FD_ISSET\n");
- workersock = accept(mastersock,(struct sockaddr *)&socketaddr,(socklen_t *)&addrlen);
- //sprintf("Received connection from a client %s port %d,sock id %d",inet_ntoa(socketaddr.sin_addr),ntohs(socketaddr.sin_port),workersock);
- /*debug*/
- printf("worlersock:%d\n",workersock);
- if(workersock >= 0){
- printf("start to send card info !\r \n");
- memset(BUF,'2',256);
- //write(workersock,BUF,256);
- /*debug*/
- //printf("sockId:%d\n",workersock);
- send(workersock,BUF,256,0);
- //sleep(1);
- int result = recv(workersock,BUF,256,0);
- //(workersock,BUF,256);
- printf("result:%d:,recv data:%s\n",result,BUF);
- //close(workersock);
- }
- }
- }else if(0 == selectVal){
- printf("warning: select retun 0");
- sleep(1);
- }else{
- printf("error:select return error");
- sleep(1);
- }
- }
-
- close(mastersock);
- return 0;
- }
复制代码
- //client.c
- #include<stdio.h>
- #include<stdlib.h>
- #include<unistd.h>
- #include<string.h>
- #include<sys/socket.h>
- #include<sys/types.h>
- #include<netinet/in.h> /*struct in_addr*/
- #include<errno.h>
- #include<time.h>
- #include<sys/time.h>
- #include<stdarg.h> /*va_list*/
- #include<signal.h> /*sigaction*/
- #include<arpa/inet.h>
- #include<ctype.h>
- #include<sys/ioctl.h>
- #include<netdb.h>
- #define SERVER_IP "192.168.141.135"
- #define SERVER_PORT "21000"
- #ifndef __cplusplus
- typedef char bool;
- #define true 1
- #define TRUE 1
- #define false 0
- #define FALSE 0
- #endif
- typedef signed long long SInt64;
- #define BUFSIZE 256
- #define SEC 3
- #define TIMEOUT 5
- #define PROTO "tcp"
- const char *SafeLibErrorLoc;
- int SafeLibErrno = 0;
- FILE *SafeLibErrorDest = NULL;
- int safeclose(int fd);
- void HandleError(int ecode, const char *const caller,const char *fmt,...);
- int clientconnect(const char *host,const char *port, const char *proto);
- int resolveproto(const char *proto);
- SInt64 Milliseconds();
- int prototype(const char *proto);
- void socketaddr_init(struct sockaddr_in *socketaddr);
- int socketaddr_service(struct sockaddr_in *socketaddr, const char *service, const char *proto);
- int socketaddr_host(struct sockaddr_in *socketaddr, const char *host);
- int server_init(const char *port, const char *proto);
- static int checkstring(const char *string);
- //主要部分
- int main(void)
- {
- int sockId = -1;
- int count = 0;
- int status = 0;
- int timeOutCount;
- fd_set selectSet, oriSelectSet;
- SInt64 sStart = 0;
- SInt64 snow = 0;
- SInt64 sRecvLen=0,sLastRecvLen=0;
- struct timeval timeOut;
- int selectRvalue;
- int result;
- char cefBuff[BUFSIZE];
- float fSafeNumber=0.0;
- while(1){
- struct in_addr addr;
- char* serverIpStr;
- char* tmpPort;
- bool bMultiCast = false;
- bool isUDP = false;
- char IPFirst[4] = {0};
- long nIpFirst;
- int initFlag = 1;
- status = 0;
- timeOutCount = 0;
- char Proto[4] = PROTO;
-
- if(sockId >= 0){
- safeclose(sockId);
- sockId = -1;
- sleep(1);
- }
-
- //char *ip = SERVER_IP;
- //初始化
- //addr.s_addr = (in_addr_t)ip;
- //strcpy(serverIpStr,inet_ntoa(addr));
- //sprintf(tmpPort,"%d",(int)SERVER_PORT);
- serverIpStr = SERVER_IP;
- tmpPort = SERVER_PORT;
- /*debug*/
- printf("serverIpStr:%s\n",serverIpStr);
-
- for(count = 0; count < 3; count++){
- sockId = clientconnect(serverIpStr,tmpPort,Proto);
-
- printf("sockId:%d\n",sockId);
- if(sockId >= 0) break;
- sleep(1);
- }
- /*debug*/
- printf("out for count <3\n");
- if(sockId < 0){
- sprintf("fail, connect lve ip is %s,port id %s,try times is %d\n NOW GO TO TRY_OTHER:",serverIpStr,tmpPort,count);
- continue;
- }
- if(bMultiCast){
- struct ip_mreq x;
- unsigned long ipaddr_t = addr.s_addr;
- memcpy(&x.imr_multiaddr.s_addr,&ipaddr_t,sizeof(ipaddr_t));
- if(setsockopt(sockId,SOL_IP,IP_ADD_MEMBERSHIP,(char *)&x,sizeof(struct ip_mreq)) == -1){
- printf("setsockopt error: %s\n",strerror(errno));
- }
- }
-
- printf("success,connect lve ip:%s,port %s,sockId %d\n",serverIpStr,tmpPort,sockId);
- FD_ZERO(&oriSelectSet);
- FD_SET(sockId,&oriSelectSet);
- sStart = Milliseconds();
- while(initFlag){
- memcpy(&selectSet,&oriSelectSet,sizeof(selectSet));
- /*debug*/
- printf("while(initFlag)\n");
- timeOut.tv_sec =3 ;
- timeOut.tv_usec = 0;
-
- selectRvalue = select(sockId+1,&selectSet,NULL,NULL,&timeOut);
- selectRvalue = 1;
- if(selectRvalue > 0){
- timeOutCount = 0;
- printf("in it\n");
- if(FD_ISSET(sockId,&selectSet)){
- //关键处
- int result = recv(sockId,cefBuff,BUFSIZE,0);
- if(result){
- printf("recv data:%s\n",cefBuff);
- sleep(1);
- memset(cefBuff,'1',BUFSIZE);
- printf("send:%s\n",cefBuff);
- int i;
- while(1){
- for(i = 0; i < 100; i++)
- send(sockId,cefBuff,BUFSIZE,0);
- }
- }
- }//监管
-
- snow = Milliseconds();
- if((snow-sStart) >= SEC*1000){
- long ltotal = sRecvLen - sLastRecvLen;
- ltotal *= 8;
- if(ltotal <(long)fSafeNumber){
- initFlag = 0;
- sRecvLen = sLastRecvLen =0;
- break;
- }
- sStart = snow;
- sLastRecvLen = sRecvLen;
- }
- }else if(selectRvalue == 0){
- //超时计数
- sleep(2);
- if(++timeOutCount >= TIMEOUT){
- printf("time out\n");
- initFlag = 0;
- }
- continue;
- }else{
- //系统出错
- if(errno != EINTR)
- printf("error sockId :%d",sockId);
-
- initFlag = 0;
- sleep(2);
- continue;
- }
- }
- }
- printf("exit\n");
- safeclose(sockId);
- }
- /*安全退出,关闭 sock*/
- int safeclose(int fd)
- {
- int retval;
-
- retval = close(fd);
- if(fd == -1)
- HandleError(errno,"close","Possible serious problem: close failed");
- return retval;
- }
- /*错误处理*/
- void HandleError(int ecode, const char *const caller,const char *fmt,...)
- {
- va_list fmtargs;
- struct sigaction sastruct;
- FILE *of = (SafeLibErrorDest)? SafeLibErrorDest: stderr;
-
- SafeLibErrorLoc = caller;
- SafeLibErrno = ecode;
-
- va_start(fmtargs,fmt);
- fprintf(of,"***Error in %s:",caller);
- vfprintf(of,fmt,fmtargs);
- va_end(fmtargs);
- fprintf(of,"\n");
-
- if(ecode){
- fprintf(of,"*** Error cause: %s\n",strerror(ecode));
- }
- sigaction(SIGUSR1,NULL,&sastruct);
- if(sastruct.sa_handler != SIG_DFL){
- raise(SIGUSR1);
- }
- }
- /*进行链接有超时机制*/
- int clientconnect(const char *host,const char *port, const char *proto)
- {
- int sockid = -1;
- int nProto = resolveproto(proto);
- /*debug*/
- printf("nProto:%d----port:%s,proto:%s\n",nProto,port,proto);
- if(nProto == 17){
- sockid = server_init(port ,proto);
- }else{
- unsigned long non_blocking = 1;
- unsigned long blocking = 0;
- struct sockaddr_in socketaddr;
- socketaddr_init(&socketaddr);
- socketaddr_service(&socketaddr,port,proto);
- socketaddr_host(&socketaddr,host);
- sockid = socket(PF_INET,prototype(proto),nProto);
- if(sockid < 0){
- return -1;
- }
- ioctl(sockid,FIONBIO,&non_blocking);
- if( -1 == connect(sockid,(struct sockaddr *)&socketaddr,sizeof(struct sockaddr))){
- struct timeval tv;
- fd_set writefds;
- int error;
- //设置链接超时时间
- tv.tv_sec = 3; //秒
- tv.tv_usec = 0; //毫秒
- FD_ZERO(&writefds);
- FD_SET(sockid,&writefds);
- if(select(sockid+1,NULL,&writefds,NULL,&tv) != 0){
- if(FD_ISSET(sockid,&writefds)){
- int len = sizeof(error);
- //针对防火墙
- if(getsockopt(sockid,SOL_SOCKET,SO_ERROR,(char *)&error,(unsigned int *)&len) < 0)
- goto error_ret;
- if(error != 0)
- goto error_ret;
- }else
- goto error_ret; //超时或出错
-
- }else
- goto error_ret;
- ioctl(sockid,FIONBIO,&blocking);
- }
- else{
-
- error_ret:
- safeclose(sockid);
- return -1;
- }
- }
- return sockid;
- }
- /*获得协议*/
- int resolveproto(const char *proto)
- {
- struct protoent *protocol;
- protocol = getprotobyname(proto);
- /*debug*/
- printf("resolveproto: proto:%s\n",proto);
- if (!protocol)
- {
- HandleError(0, "resolveproto", "getprotobyname failed for %s", proto);
- return -1;
- }
- return protocol->p_proto;
- }
- /*设置timeval*/
- SInt64 Milliseconds()
- {
- struct timeval t;
- struct timezone tz;
- gettimeofday(&t, &tz);
-
- SInt64 curTime;
- curTime = t.tv_sec;
- curTime *= 1000; // sec -> msec
- curTime += t.tv_usec / 1000; // usec -> msec
- return curTime;
- }
- /*判断是TCP或是UDP*/
- int prototype(const char *proto)
- {
- if (strcmp(proto, "tcp") == 0){
- /*debug*/
- printf("return SOCK_STREAM\n");
- return SOCK_STREAM;
- }
- if (strcmp(proto, "udp") == 0){
- printf("return SOCK_DFRAM\n");
- return SOCK_DGRAM;
- }
- return -1;
- }
- /*地址初始化*/
- void socketaddr_init(struct sockaddr_in *socketaddr)
- {
- bzero((char *) socketaddr, sizeof(*socketaddr));
- socketaddr->sin_family = AF_INET;
- }
- /*地址初始化*/
- int socketaddr_service(struct sockaddr_in *socketaddr, const char *service, const char *proto)
- {
- struct servent *serviceaddr;
- /* Need to allow numeric as well as textual data. */
- /* 0: pass right through. */
- if (strcmp(service, "0") == 0)
- socketaddr->sin_port = 0;
- else
- {/* nonzero port */
- serviceaddr = getservbyname(service, proto);
- if (serviceaddr)
- {
- socketaddr->sin_port = serviceaddr->s_port;
- }
- else
- { /* name did not resolve, try number */
- if (checkstring(service))
- { /* and it's a text name, fail. */
- HandleError(0, "socketaddr_service", "no lookup for %s/%s", service, proto);
- return -1;
- }
- if ((socketaddr->sin_port = htons((u_short)atoi(service))) == 0)
- {
- HandleError(0, "socketaddr_service", "numeric conversion failed");
- return -1;
- }
- }
- }
- return 0;
- }
- /*服务器设置地址*/
- int socketaddr_host(struct sockaddr_in *socketaddr, const char *host)
- {
- struct hostent *hostaddr;
- hostaddr = gethostbyname(host);
- if (!hostaddr)
- {
- HandleError(0, "socketaddr_host", "gethostbyname failed for %s", host);
- return -1;
- }
- memcpy(&socketaddr->sin_addr, hostaddr->h_addr, hostaddr->h_length);
- return 0;
- }
- /*服务端初始化*/
- int server_init(const char *port, const char *proto)
- {
- struct sockaddr_in socketaddr;
- int mastersock;
- int trueval = 1;
- /*debug*/
- printf("server_init,port:%s---proto:%s\n",port,proto);
- socketaddr_init(&socketaddr);
- socketaddr.sin_addr.s_addr = INADDR_ANY;
- socketaddr_service(&socketaddr, port, proto);
- mastersock = socket(PF_INET, prototype(proto), resolveproto(proto));
- if (mastersock < 0)
- {
- HandleError(errno, "serverinit", "couldn't create socket");
- return -1;
- }
- setsockopt(mastersock,SOL_SOCKET,SO_REUSEADDR,&trueval,sizeof(socklen_t));
- // if (bind(mastersock, (struct sockaddr *)&socketaddr, sizeof(socketaddr)) < 0)
- {
- HandleError(errno, "serverinit", "bind to port %s failed", port);
- return -1;
- }
- //setsockopt(mastersock, SOL_SOCKET, 0, &trueval, sizeof(trueval));
- if (prototype(proto) == SOCK_STREAM)
- {
- if (listen(mastersock, 5) < 0)
- {
- HandleError(errno, "serverinit", "listen on port %d failed", socketaddr.sin_port);
- return -1;
- }
- }
- else if (prototype(proto) == SOCK_DGRAM) {
- int buf_size = 512 * 1024;
- setsockopt(mastersock,SOL_SOCKET,SO_RCVBUF, (char *)&buf_size, sizeof(int));
- }
- return mastersock;
- }
- static int checkstring(const char *string)
- {
- unsigned int counter;
- for (counter = 0; counter < strlen(string); counter++)
- if (!(isdigit(string[counter])))
- return 1;
- return 0;
- }
复制代码 |
|