⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 tcpipmex.c

📁 A very small 250-line library (written entirely in MATLAB) that allows multiple MATLAB programs to t
💻 C
📖 第 1 页 / 共 2 页
字号:
	     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 + -