Пример #1
0
// NewClient creates, initiates, and returns a new client. This function
// should return after a connection with the server has been established
// (i.e., the client has received an Ack message from the server in response
// to its connection request), and should return a non-nil error if a
// connection could not be made (i.e., if after K epochs, the client still
// hasn't received an Ack message from the server in response to its K
// connection requests).
//
// hostport is a colon-separated string identifying the server's host address
// and port number (i.e., "localhost:9999").
func NewClient(hostport string, params *Params) (Client, error) {
	if params == nil {
		params = &Params{5, 2000, 1}
	}

	addr, err := lspnet.ResolveUDPAddr("udp", hostport)
	if err != nil {
		return nil, err
	}

	conn, err := lspnet.DialUDP("udp", nil, addr)
	if err != nil {
		return nil, err
	}

	c := &client{
		comm:    NewCommon(addr, params),
		connUDP: conn,

		readBufToAppChan:   make(chan *Message),
		netToReadWinChan:   make(chan *Message),
		epochToReadWinChan: make(chan *Message),

		appToWriteBufChan:   make(chan *Message),
		netToWriteBufChan:   make(chan *Message),
		epochToWriteBufChan: make(chan *Message),

		connChan: make(chan *Message),

		appCloseSynChan:     make(chan bool, 1),
		netLostCloseSynChan: make(chan bool, 1),
	}

	// go c.manageReceivedMsg()
	go c.handleEpoch()
	go c.readFromServer()
	go c.handleReadSlideWindow()
	go c.handleWriteSlideWindow()

	//init lock
	// c.connIDSynChan <- 0

	c.appCloseSynChan <- false
	c.netLostCloseSynChan <- false

	//start connect
	c.writeToServer(c.generateMsg(MsgConnect, 0, nil))
	connMsg := <-c.connChan
	if connMsg.Type == MsgAck && connMsg.SeqNum == 0 {
		SetValueToIntChan(c.comm.connIDSynChan, connMsg.ConnID)
		SetValueToBoolChan(c.comm.isConnectedSynChan, true)
		c.comm.connID = connMsg.ConnID
		fmt.Println("Client:", c.comm.connID, "Start")
		return c, nil
	}
	return nil, errors.New("Connection failed")
}
Пример #2
0
// dial the remote server using the hostport given, used on client side
func (h *networkUtility) dial(hostport string) error {
	serverAddr, err := lspnet.ResolveUDPAddr("udp", hostport)
	if err != nil {
		return err
	}
	conn, err := lspnet.DialUDP("udp", nil, serverAddr)
	if err != nil {
		return err
	}
	h.conn = conn
	return nil
}
Пример #3
0
func (now *Connect) dial(hostport string) error {
	serverAddr, err := lspnet.ResolveUDPAddr("udp", hostport)
	if err != nil {
		return err
	}
	conn, err := lspnet.DialUDP("udp", nil, serverAddr)
	if err != nil {
		return err
	}
	now.addr = serverAddr
	now.conn = conn
	return nil
}
func (c *client) StartDial(hostport string) error {
	var err error
	c.sAddr, err = lspnet.ResolveUDPAddr("udp", hostport)
	if err != nil {
		fmt.Println("Unable to resolve server UDP addr ", hostport)
		return err
	}
	go c.handleMessages()
	go c.ticking()

	c.conn, err = lspnet.DialUDP("udp", nil, c.sAddr)

	if err != nil {
		fmt.Println("cannot dial to port ", hostport)
		return err
	}

	fmt.Println("dial to ", hostport)

	// send connect message
	c.writeChan <- clientWriteData{MsgConnect, 0, nil}

	// waiting for connect ack
	buf := make([]byte, 2000)
	msg := Message{}
	n, err := c.conn.Read(buf)
	if err != nil {
		fmt.Println("unable read from connection")
		msg = <-c.connSucChan
	} else {
		json.Unmarshal(buf[0:n], &msg)
	}
	switch msg.Type {
	case MsgAck:
		c.setidChan <- msg.ConnID
	default:
		return errors.New("unable to connect")
	}

	// start listen on data/ack
	go c.StartListen()

	return nil
}
Пример #5
0
func NewFixedSizeUDPClient(maxMsgSize int, serverHostPort string) (UDPClient, error) {
	serverAddr, err := net.ResolveUDPAddr("udp4", serverHostPort)
	if err != nil {
		return nil, err
	}

	// non-blocking. it won't wait for server to build connection as TCP does
	// it returns non-nil error even though the server is not running. (no connection)
	conn, err := net.DialUDP("udp", nil, serverAddr)
	if err != nil {
		return nil, err
	}

	return &FixedSizeUDPClient{
		maxMsgSize: maxMsgSize,
		serverAddr: serverAddr,
		conn:       conn,
		closed:     false,
	}, nil
}
Пример #6
0
// NewClient creates, initiates, and returns a new client. This function
// should return after a connection with the server has been established
// (i.e., the client has received an Ack message from the server in response
// to its connection request), and should return a non-nil error if a
// connection could not be made (i.e., if after K epochs, the client still
// hasn't received an Ack message from the server in response to its K
// connection requests).
//
// hostport is a colon-separated string identifying the server's host address
// and port number (i.e., "localhost:9999").
func NewClient(hostport string, params *Params) (Client, error) {
	c := &client{
		nextSN:             1,
		writeToServerChan:  make(chan *Message),
		readFromServerChan: make(chan *Message),
		readRequest: &requestRead{
			ask:      make(chan int),
			response: make(chan *Message),
		},
		writeRequest: &requestWrite{
			ask:      make(chan []byte),
			response: make(chan error),
		},
		readMap: make(map[int]*Message),
		// write list has order
		writeMap:  make(map[int]*Message),
		connected: make(chan int),
		flag:      false,
		connect:   false,

		// variables for window size
		windowSize: params.WindowSize,
		// send to client data
		nextSmallestAck: 1,
		mapAck:          make(map[int]bool),
		mapNeedAck:      make(map[int]*Message),

		// receive from client data
		nextSmallestData: 1,
		// TODO: didn't need this
		mapAcked:     make(map[int]bool),
		mapReceived:  make(map[int]*Message),
		nextDataRead: 1,

		// epoch variables
		epochChan:   make(chan int),
		epochMillis: params.EpochMillis,
		epochLimit:  params.EpochLimit,
		epochNum:    0,
		lostConn:    false,

		// clsoe
		closeRequest: &requestClose{
			ask: make(chan int),
			//response: make(chan int),
			getError: make(chan error),
		},
		waitToWriteFinish: false,
		writeFinished:     make(chan int),
		waitToAckFinish:   false,
		ackFinished:       make(chan int),
		closeRead:         make(chan int, 1),
		closeEpoch:        make(chan int, 1),
		closeEvent:        make(chan int, 1),
	}

	// connect to server
	addr, err := lspnet.ResolveUDPAddr("udp", hostport)

	if err != nil {
		return nil, err
	}

	conn, err := lspnet.DialUDP("udp", nil, addr)
	if err != nil {
		return nil, err
	}
	fmt.Println("new client")

	c.conn = conn
	c.addr = addr
	fmt.Println("70")

	////fmt.Println("74")

	go c.readMessage()
	go c.handleMessage()
	go c.epochFire()

	msg := NewConnect()
	c.writeToServerChan <- msg

	<-c.connected
	//fmt.Println("Client 156: connect success")

	return c, nil
}
Пример #7
0
// NewClient creates, initiates, and returns a new client. This function
// should return after a connection with the server has been established
// (i.e., the client has received an Ack message from the server in response
// to its connection request), and should return a non-nil error if a
// connection could not be made (i.e., if after K epochs, the client still
// hasn't received an Ack message from the server in response to its K
// connection requests).
//
// hostport is a colon-separated string identifying the server's host address
// and port number (i.e., "localhost:9999").
func NewClient(hostport string, params *Params) (Client, error) {
	c := &client{
		hostport: hostport,
		params:   params,
		connID:   -1,
		seqNum:   0,

		conn:      nil,
		connected: false,
		connOpen:  make(chan struct{}),
		connClose: make(chan struct{}),
		connMsg:   NewConnect(),

		dataMsgTo: make(chan *Message),
		dataMsgFr: make(chan *Message),

		dataMsgTokens: make(chan struct{}, params.WindowSize),

		seqNumToActChan:    make(chan map[int]*Activity),
		seqNumToAckMsgChan: make(chan map[int]*Message),

		dataWrWindow: make(chan *SlideWindow, 1),
		dataRdWindow: make(chan *SlideWindow, 1),
	}

	raddr, err := lspnet.ResolveUDPAddr("udp", hostport)
	if err != nil {
		return nil, err
	}
	conn, err := lspnet.DialUDP("udp", nil, raddr)
	if err != nil {
		return nil, err
	}

	c.conn = conn
	c.dataWrWindow <- &SlideWindow{
		seqNumLower: 1,
		seqNumUpper: 1 + c.params.WindowSize,
	}
	c.dataRdWindow <- &SlideWindow{
		seqNumLower: 1,
		seqNumUpper: 1 + c.params.WindowSize,
	}

	go c.onWrite()
	go c.onRead()
	go c.epoch()
	go c.connect()

	for {
		select {
		case <-c.connOpen:
			c.connected = true
			return c, nil
		case <-c.connClose:
			c.connected = false
			return nil, errors.New("connection not yet established")
		}
	}

	return nil, errors.New("not yet implemented")
}