<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def _CreateZMQSocket(self):
 """Creates a ZeroMQ socket."""

    logger.debug('Creating socket for {0:s}'.format(self.name))

    if not self._zmq_context:
      self._zmq_context = zmq.Context()

    # The terminate and close threading events need to be created when the
    # socket is opened. Threading events are unpickleable objects and cannot
    # passed in multiprocessing on Windows.

    if not self._terminate_event:
      self._terminate_event = threading.Event()

    if not self._closed_event:
      self._closed_event = threading.Event()

    if self._zmq_socket:
      logger.debug('Closing old socket for {0:s}'.format(self.name))
      self._zmq_socket.close()
      self._zmq_socket = None

    self._zmq_socket = self._zmq_context.socket(self._SOCKET_TYPE)
    self._SetSocketTimeouts()
    self._SetSocketHighWaterMark()

    if self.port:
      address = '{0:s}:{1:d}'.format(self._SOCKET_ADDRESS, self.port)
      if self.SOCKET_CONNECTION_TYPE == self.SOCKET_CONNECTION_CONNECT:
        self._zmq_socket.connect(address)
        logger.debug('{0:s} connected to {1:s}'.format(self.name, address))
      else:
        self._zmq_socket.bind(address)
        logger.debug(
            '{0:s} bound to specified port {1:s}'.format(self.name, address))
    else:
      self.port = self._zmq_socket.bind_to_random_port(self._SOCKET_ADDRESS)
      logger.debug(
          '{0:s} bound to random port {1:d}'.format(self.name, self.port))