📄 tcpipmex.c
字号:
move_ipi(IPI_FREE); init_ipi(conn_fd,STATUS_SERVER); my_mexReturnValue(nlhs,plhs,ipi_index); } else { my_mexReturnValue(nlhs,plhs,-1); } } break; default: mexErrMsgTxt("Unknown number for called function! Not implemented in this verion?"); break; } debug_view_ipi_status("EXIT");}/******************************************************************* *//* Function Creating socket for later listning for connections on specified port. Returns socket fid after */int tcpipsocket(int port){// int new_fd; /* new connection on new_fd */ int sockfd; struct sockaddr_in my_addr; /* my address information */// int sin_size; const int on=1; const int off=0; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { return -1; } my_addr.sin_family = AF_INET; /* host byte order */ my_addr.sin_port = htons(port); /* short, network byte order */ my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */ memset(&(my_addr.sin_zero),0, 8); /* zero the rest of the struct */ setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(const char *)&on,sizeof(on)); if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) \ == -1) { close(sockfd); return -1; } nonblockingsocket(sockfd); if (listen(sockfd, TCPIP_BACKLOG) == -1) { close(sockfd); return -1; } return sockfd;}/* Listen to socket and returns connection if their is one... else it returns -1 */int tcpiplisten(int sockfd){ int new_fd; int sin_size; sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&ipi[ipi_index].remote_addr, \ &sin_size)) == -1) { return -1; } setsockopt(new_fd,SOL_SOCKET,SO_KEEPALIVE,(void *)1,0); /* realy needed?*/ return new_fd;}/*******************************************************************************//* Checks that given index is valid index and set current index, "ipi_index" *//* to that point. If index is IPI_FREE (-1) then is seatch done for a free one *//* Returns 1 On success. 0 on error */int move_ipi(int idx){ if(idx>=0) { ipi_index=idx; if(ipi[ipi_index].status==STATUS_FREE) mexErrMsgTxt("No valid handler! already closed?\n"); return 1; } debug_view_ipi_status("START MOVE"); if(idx==IPI_CURRENT) mexErrMsgTxt("Current fid (-2) no longer supported!\n"); if(idx>=MAX_IPI) mexErrMsgTxt("Unvalid value of handler!\n"); if(idx==IPI_FREE) /* Move ipi_index until it find a free non used struct */ { for(ipi_index=0;ipi_index<MAX_IPI;ipi_index++) { debug_view_ipi_status("STEP MOVE"); if(ipi[ipi_index].status==STATUS_FREE) { ipi[ipi_index].status=STATUS_NOCONNECT; return 1; } } mexErrMsgTxt("To many open connection! Forgot to close?\n"); } if(idx<0) mexErrMsgTxt("Unvalid value of handler!\n"); return 0;}/*******************************************************************************//* Puts double scalar in matlab variable in the array of return argument for mex*/void my_mexReturnValue(int nlhs, mxArray *plhs[],double val){ if((ret_args>nlhs) && (ret_args>1)) { printf("No use for all return arguments!\n"); return; } plhs[ret_args]=mxCreateDoubleMatrix(1,1,mxREAL); if(plhs[ret_args]==NULL) mexErrMsgTxt("Matrix creation error! Lack of memory?"); else { *mxGetPr(plhs[ret_args])=val; ret_args++; }}/******************************************************************************//* Puts string as matlab char char variable in array of return argument for mex*/void my_mexReturnString(int nlhs, mxArray *plhs[], const char *str){ if(ret_args>nlhs & ret_args>1) return; plhs[ret_args]=mxCreateString(str); if(plhs[ret_args]==NULL) mexErrMsgTxt("String creation error! Lack of memory?"); else ret_args++;}/******************************************************************************//* Puts part of string as char variable in array of return arguments from mex */void my_mexReturnCharArray(int nlhs, mxArray *plhs[], const char *buff,int bufflen){ int ndim = 2, dims[2]; mxArray *array_ptr; mxChar *pr; int c; unsigned char *ubuff; /* src buffert pointer as unsigned char. */ if(bufflen==0) { dims[0]=0; dims[1]=0; } else { dims[0]=1; dims[1]=bufflen; } if(ret_args>nlhs & ret_args>1) return; /* Create a 2-Dimensional character mxArray. */ array_ptr = mxCreateCharArray(ndim, dims); if (array_ptr == NULL) mexErrMsgTxt("Could not create Character mxArray."); pr = (mxChar *)mxGetPr(array_ptr); ubuff=(unsigned char *)buff; /* readout data as unsigned */ for (c=0;c<bufflen;c++) { *pr = (mxChar)(*ubuff); ubuff++; pr++; } plhs[ret_args]=array_ptr; ret_args++;}/****************************************************************************//* This function is called on unloading of mex-file */void CleanUpMex(void){ if(closeall()) /* close all still open connections...*/ { /* ....if not all alread closed put out a matlab warning*/ /* should an breaking error message be better ??? */ mexWarnMsgTxt("Unloading mex file!\n" "Unclosed tcpip connections will be lost!!!!\n"); }#ifdef WIN32 WSACleanup();#else signal(SIGPIPE,SIG_DFL); /*reset SIGPIPE to default. Is this good ??? */#endif}/******************************************************************* *//* Function to close all still open tcpip connections */int closeall(void){ for(ipi_index=0;ipi_index<MAX_IPI;ipi_index++) close_ipi(); return 0;}/******************************************************************* *//* Copys a matlab Char array to a char * string buffer*/void CopymxCharArray2Buff(const mxArray *array,char *buff,int bufflen){ int arraylen; int a; mxChar *pr; arraylen=mxGetM(array)*mxGetN(array); pr = (mxChar *)mxGetPr(array); for(a=0;a<bufflen & a<arraylen;a++) { *buff=*pr; buff++; pr++; }}/******************************************************************* *//* Function Creating socket and waits for a connection on specified port. Returns connection fid after removing socket to avoid more connections */int tcpipserver(int port){ int sockfd, new_fd; /* listen on sock_fd, new connection on new_fd */ struct sockaddr_in my_addr; /* my address information */ int sin_size; if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1) { return -1; } my_addr.sin_family = AF_INET; /* host byte order */ my_addr.sin_port = htons(port); /* short, network byte order */ my_addr.sin_addr.s_addr = INADDR_ANY; /* auto-fill with my IP */ memset(&(my_addr.sin_zero),0, 8); /* zero the rest of the struct */ setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,(void *)1,0); if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) \ == -1) { close(sockfd); return -1; } if (listen(sockfd, TCPIP_BACKLOG) == -1) { close(sockfd); return -1; } sin_size = sizeof(struct sockaddr_in); if ((new_fd = accept(sockfd, (struct sockaddr *)&ipi[ipi_index].remote_addr, \ &sin_size)) == -1) { close(sockfd); return -1; } close(sockfd); setsockopt(new_fd,SOL_SOCKET,SO_KEEPALIVE,(void *)1,0); /* realy needed?*/ init_ipi(new_fd,STATUS_SERVER); return new_fd;}/********************************************************************//* Init current record with values */void init_ipi(int fid,int status){ ipi[ipi_index].writetimeout=0; ipi[ipi_index].readtimeout=0; ipi[ipi_index].fid=fid; ipi[ipi_index].status=status; ipi[ipi_index].buff=NULL; ipi[ipi_index].callback[0]='\0'; ipi[ipi_index].bufflen=0; ipi[ipi_index].buffdatalen=0; if(ipi[ipi_index].fid>=0) nonblockingsocket(ipi[ipi_index].fid); /* Non blocking read!*/}/********************************************************************//* Close ipi struct */void close_ipi(){ if(ipi[ipi_index].fid>=0) close(ipi[ipi_index].fid); if(ipi[ipi_index].buff==NULL) myrealloc(ipi[ipi_index].buff,0); init_ipi(-1,STATUS_FREE);}/********************************************************************//* Turn handler on */void get_sigpipe_on(void){#ifndef WIN32 void *rethand; rethand=(void *)signal(SIGPIPE,get_sigpipe_handler); /* If signal hander was not tcpipmex own handler then is must be matlabs...*/ if(rethand!=get_sigpipe_handler && rethand>NULL ) /* .... then store it to have when restoring with "get_signal_off() */ matlab_signal_handler=rethand;#endif}/* Turn handler off */void get_sigpipe_off(void){// void *rethand;#ifndef WIN32 rethand=(void *)signal(SIGPIPE,matlab_signal_handler); if(rethand!=get_sigpipe_handler) mexErrMsgTxt("Something (in matlab/operating system ??) has replaced tcpipmex signal handler.\n" "Please report this bug in tcpip toolbox to: Peter.Rydsater@ite.mh.se.\n" "Report tcpip toolbox, OS and matlab version.");#endif}/********************************************************************//* Handler for signals when tcpip pipe is broken */void get_sigpipe_handler(int sig){ get_sigpipe_on(); /* Turn on handler agian for signal implementations where it is ... automatic turned of after each call.*/ ipi[ipi_index].status=STATUS_NOCONNECT; mexPrintf("\nSIGPIPE -> TCPIP PIPE DISCONNECTED!\n"); /* Just for debugging purpose...*/}/********************************************************************//* Writes from specified position (pointer) in buffer of spec. length*/int writedata(char *buff,int len){ int sentlen=0; int retval=0; int lastsize=1000000; if(ipi[ipi_index].status<=STATUS_SERVSOCKET) return 0; get_sigpipe_on(); while(sentlen<len) { if(lastsize<1000) usleep(2000); retval=send(ipi[ipi_index].fid,&buff[sentlen],len-sentlen,0); if(ipi[ipi_index].status==STATUS_NOCONNECT) /* If Disconnected then exit read loop */ break; lastsize=retval>0?retval:0; sentlen+=lastsize; if(retval<0 && s_errno!=EWOULDBLOCK) { ipi[ipi_index].status=STATUS_NOCONNECT; perror( "send()" ); mexPrintf("\nERROR -> TCPIP PIPE DISCONNECTED!\n"); close(ipi[ipi_index].fid); } } get_sigpipe_off(); return sentlen;}/********************************************************************//* Read specified length from network to input buffer */void read2buff(int len){// int i; int retval; int readlen; if(len==0) return; if(ipi[ipi_index].status<=STATUS_SERVSOCKET) /* If not read/write fid (broken pipe) then exit. */ return; /* If exsisting buffer is to small, then realloc a new and move data to it. */ if(len>ipi[ipi_index].bufflen) { ipi[ipi_index].buff=(char *)myrealloc(ipi[ipi_index].buff,len); if(ipi[ipi_index].buff==NULL) mexErrMsgTxt("Not enouth of memory for allocation of read buffert."); ipi[ipi_index].bufflen=len; } /* Read only to buffert if their is'nt already anouth. */ if(ipi[ipi_index].buffdatalen<len) { get_sigpipe_on(); /* Turn on "take care of broken tcpip pipes" */ retval=recv(ipi[ipi_index].fid, &ipi[ipi_index].buff[ipi[ipi_index].buffdatalen], len-ipi[ipi_index].buffdatalen, 0); readlen=retval>0?retval:0; ipi[ipi_index].buffdatalen+=readlen; if(retval==0) { ipi[ipi_index].status=STATUS_NOCONNECT; mexPrintf("\nFIN -> TCPIP PIPE DISCONNECTED!\n"); close(ipi[ipi_index].fid); } else if(retval<0 && s_errno!=EWOULDBLOCK) { ipi[ipi_index].status=STATUS_NOCONNECT; perror( "recv()" ); mexPrintf("\nERROR -> TCPIP PIPE DISCONNECTED!\n"); close(ipi[ipi_index].fid); } get_sigpipe_off(); /* turn off "take care..." */ }}/* Removes specifed number of characters from buffer that is readed into matlab.*/void removefrombuff(int len){ int newlen; if(len>0) { newlen=ipi[ipi_index].buffdatalen-len; /* Calc new buff length;*/ newlen=newlen>0?newlen:0; /* Not allow negative length.*/ memmove(&(ipi[ipi_index].buff[0]), &(ipi[ipi_index].buff[len]),newlen); /* Remove old data in buff;*/ ipi[ipi_index].buffdatalen=newlen; /* Set new length.*/ } if(ipi[ipi_index].bufflen>MINBUFFSIZE & ipi[ipi_index].buffdatalen<=MINBUFFSIZE) { ipi[ipi_index].buff=myrealloc(ipi[ipi_index].buff,MINBUFFSIZE); ipi[ipi_index].bufflen=MINBUFFSIZE; if(ipi[ipi_index].buff==NULL) { ipi[ipi_index].bufflen=0; mexErrMsgTxt("Not enouth of memory for reallocation" " of smaller read buffert."); } } }/* A "wrapper" function for memory allocation. Most for debuging /tracing purpose */void *myrealloc(void *ptr,int newsize){ ptr=realloc(ptr,newsize); return ptr;}/* DEBUGING FUNCTION */void __debug_view_ipi_status(char *str){ int a; mexPrintf("%s\n",str); for(a=0;a<5;a++) { mexPrintf("[%02d] FID:%02d STATUS:%02d",a,ipi[a].fid,ipi[a].status); if(a==ipi_index) mexPrintf("<--\n"); else mexPrintf("\n"); } mexPrintf("--------------------\n");}/* Windows implementation of perror() function */#ifdef WIN32void perror( char *context ){ int wsa_err; wsa_err = WSAGetLastError(); mexPrintf( "[%s]: WSA error: ", context ); switch ( wsa_err ) { case WSANOTINITIALISED: mexPrintf( "WSANOTINITIALISED\n" ); break; case WSAENETDOWN: mexPrintf( "WSAENETDOWN \n" ); break; case WSAEADDRINUSE: mexPrintf( "WSAEADDRINUSE \n" ); break; case WSAEACCES: mexPrintf( "WSAEACCES \n" ); break; case WSAEINTR: mexPrintf( "WSAEINTR \n" ); break; case WSAEINPROGRESS: mexPrintf( "WSAEINPROGRESS \n" ); break; case WSAEALREADY: mexPrintf( "WSAEALREADY \n" ); break; case WSAEADDRNOTAVAIL: mexPrintf( "WSAEADDRNOTAVAIL \n" ); break; case WSAEAFNOSUPPORT: mexPrintf( "WSAEAFNOSUPPORT \n" ); break; case WSAEFAULT: mexPrintf( "WSAEFAULT \n" ); break; case WSAENETRESET: mexPrintf( "WSAENETRESET \n" ); break; case WSAENOBUFS: mexPrintf( "WSAENOBUFS \n" ); break; case WSAENOTSOCK: mexPrintf( "WSAENOTSOCK \n" ); break; case WSAEOPNOTSUPP: mexPrintf( "WSAEOPNOTSUPP \n" ); break; case WSAESHUTDOWN: mexPrintf( "WSAESHUTDOWN \n" ); break; case WSAEWOULDBLOCK: mexPrintf( "WSAEWOULDBLOCK \n" ); break; case WSAEMSGSIZE: mexPrintf( "WSAEMSGSIZE \n" ); break; case WSAEHOSTUNREACH: mexPrintf( "WSAEHOSTUNREACH \n" ); break; case WSAEINVAL: mexPrintf( "WSAEINVAL \n" ); break; case WSAECONNREFUSED: mexPrintf( "WSAECONNREFUSED \n" ); break; case WSAECONNABORTED: mexPrintf( "WSAECONNABORTED \n" ); break; case WSAECONNRESET: mexPrintf( "WSAECONNRESET \n" ); break; case WSAEISCONN: mexPrintf( "WSAEISCONN \n" ); break; case WSAENOTCONN: mexPrintf( "WSAENOTCONN \n" ); break; case WSAETIMEDOUT: mexPrintf( "WSAETIMEDOUT \n" ); break; default: mexPrintf( "Unknown(%d) error!\n", wsa_err ); break; } return;}#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -