MySQL在Windows平台下通信方式

来源:互联网 发布:学校网络管理制度 编辑:程序博客网 时间:2024/05/29 14:32

   在Windows平台下,MySQL可以使用三种方式和客户单通信。分别是套接字(SOCKET)、管道(Pipe)、共享内存(ShareMemory).

而到底使用哪种方式,MySQL在编译的时候就已经决定了,在vio.c文件中会对通信方式进行初始化(vio_init函数,见后面),而对于不同类型的通信方式肯定会有不同的函数定义了,这些指针函数就定义在viosocket.c当中。这其中又有连个函数吸引我注意的,因为一开始我没有理解是什么意思(见后面代码中注释 )。

 

/*

 * Helper to fill most of the Vio* withdefaults.

 */

 

static void vio_init(Vio* vio, enum enum_vio_type type,

                     my_socketsd, HANDLEhPipe, uintflags)

{

  DBUG_ENTER("vio_init");

  DBUG_PRINT("enter", ("type:%d  sd: %d  flags: %d", type, sd, flags));

 

#ifndef HAVE_VIO_READ_BUFF

  flags&=~VIO_BUFFERED_READ;

#endif

  bzero((char*) vio, sizeof(*vio));

  vio->type       = type;

  vio->sd = sd;

  vio->hPipe     = hPipe;

  vio->localhost= flags& VIO_LOCALHOST;

  if ((flags & VIO_BUFFERED_READ)&&

      !(vio->read_buffer= (char*)my_malloc(VIO_READ_BUFFER_SIZE,MYF(MY_WME))))

    flags&=~VIO_BUFFERED_READ;

#ifdef _WIN32

  if (type == VIO_TYPE_NAMEDPIPE)

  {

    vio->viodelete    =vio_delete;

    此处省略N个字

    vio->timeout=vio_win32_timeout;

    /* Set defaulttimeout */

    vio->read_timeout_ms= INFINITE;

    vio->write_timeout_ms= INFINITE;

    vio->pipe_overlapped.hEvent=CreateEvent(NULL,TRUE, FALSE,NULL);

    DBUG_VOID_RETURN;

  }

#endif

#ifdef HAVE_SMEM

  if (type == VIO_TYPE_SHARED_MEMORY)

  {

    vio->viodelete    =vio_delete;

    vio->vioerrno     =vio_errno;

    vio->read          =vio_read_shared_memory;

    vio->write         =vio_write_shared_memory;

    vio->fastsend     =vio_fastsend;

    此处省略N个字

    vio->has_data      =has_no_data;

 

    /* Currently,shared memory is on Windows only, hence the below is ok*/

    vio->timeout= vio_win32_timeout;

    /* Set defaulttimeout */

    vio->read_timeout_ms= INFINITE;

    vio->write_timeout_ms= INFINITE;

    DBUG_VOID_RETURN;

  }

#endif  

#ifdef HAVE_OPENSSL

  if (type == VIO_TYPE_SSL)

  {

    vio->viodelete    =vio_ssl_delete;

    vio->vioerrno     =vio_errno;

    vio->read            =vio_ssl_read;

    此处省略N个字

    vio->has_data      =vio_ssl_has_data;

    DBUG_VOID_RETURN;

  }

#endif /* HAVE_OPENSSL */

  vio->viodelete       =vio_delete;

  此处省略N个字

  vio->is_connected    =vio_is_connected;

  vio->has_data=       (flags & VIO_BUFFERED_READ)?

                            vio_buff_has_data : has_no_data;

  DBUG_VOID_RETURN;

}

 

 

这连个函数就是网络读取函数:

size_t vio_read(Vio * vio, uchar* buf, size_t size)

{

  size_t r;

  DBUG_ENTER("vio_read");

  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,

                       (uint) size));

 

  /* Ensure nobody uses vio_read_buff and vio_read simultaneously */

  DBUG_ASSERT(vio->read_end == vio->read_pos);

#ifdef __WIN__

  r = recv(vio->sd, buf, size,0);

#else

  errno=0;/* For linux */

  r = read(vio->sd, buf, size);

#endif /* __WIN__ */

#ifndef DBUG_OFF

  if (r == (size_t) -1)

  {

    DBUG_PRINT("vio_error", ("Got error %d during read",errno));

  }

#endif /* DBUG_OFF */

  DBUG_PRINT("exit", ("%ld", (long) r));

  DBUG_RETURN(r);

}

 

 

/*

  Buffered read: if average read size is small it may

  reduce number of syscalls.

*/

 

size_t vio_read_buff(Vio *vio, uchar* buf, size_t size)

{

  size_t rc;

#define VIO_UNBUFFERED_READ_MIN_SIZE 2048

  DBUG_ENTER("vio_read_buff");

  DBUG_PRINT("enter", ("sd: %d  buf: 0x%lx  size: %u", vio->sd, (long) buf,

                       (uint) size));

 

  if (vio->read_pos < vio->read_end)

  {

    rc= min((size_t) (vio->read_end - vio->read_pos), size);

    memcpy(buf, vio->read_pos, rc);

    vio->read_pos+= rc;

    /*

      Do not try to read from the socket now even if rc < size:

      vio_read can return -1 due to an error or non-blocking mode, and

      the safest way to handle it is to move to a separate branch.

    */

  }

  else if (size < VIO_UNBUFFERED_READ_MIN_SIZE)

  {

    rc= vio_read(vio, (uchar*) vio->read_buffer, VIO_READ_BUFFER_SIZE);

    if (rc != 0 && rc != (size_t) -1)

    {

      if (rc > size)

      {

        vio->read_pos= vio->read_buffer + size;

        vio->read_end= vio->read_buffer + rc;

        rc= size;

      }

      memcpy(buf, vio->read_buffer, rc);

    }

  }

  else

    rc= vio_read(vio, buf, size);

  DBUG_RETURN(rc);

#undef VIO_UNBUFFERED_READ_MIN_SIZE

}

 

从中可以看出,使用缓存的话,可以缓存VIO_READ_BUFFER_SIZE多个字符,意思是避免小的读取可以直接在缓存中读取。只看此处我认为如果当缓存中还有数据,而要读取的数据大于缓存中数据的时候,此处只返回了缓存中的数据。而如果此时其实套接自上是有数据的呢。

要知此处究竟,还须继续努力地看了。

其他的管道、共享内存应该是同样的处理方式了,我也没有去看,先走通一遍吧