// 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") }
// listen to incoming UDP data using the given hostport, used on server side func (h *networkUtility) listen(hostport string) error { serverAddr, err := lspnet.ResolveUDPAddr("udp", hostport) if err != nil { return nil } conn, err := lspnet.ListenUDP("udp", serverAddr) if err != nil { return err } h.conn = conn return nil }
func (now *Connect) listen(hostport string) error { serverAddr, err := lspnet.ResolveUDPAddr("udp", hostport) if err != nil { return nil } conn, err := lspnet.ListenUDP("udp", serverAddr) if err != nil { return err } now.conn = conn now.addr = serverAddr return nil }
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 (s *server) StartListen(port string) error { uAddr, err := lspnet.ResolveUDPAddr("udp", ":"+port) if err != nil { fmt.Println("Unable to resolve UDP addr ", port) return err } s.sConn, err = lspnet.ListenUDP("udp", uAddr) if err != nil { fmt.Println("Unable to listen on port ", port) return err } go s.handleMessages() go s.ticking() for { select { case <-s.quitAllChan: fmt.Println("server quit listener") return nil default: // read a msg from UDP and check its type buf := make([]byte, 2000) n, addr, err := s.sConn.ReadFromUDP(buf) if err != nil { return err } msg := Message{} json.Unmarshal(buf[0:n], &msg) switch msg.Type { case MsgConnect: // receive a conn msg from client s.addChan <- addr case MsgData: // add to data channel if hash match, drop otherwise if hex.EncodeToString(calMD5Hash(msg)) == hex.EncodeToString(msg.Hash) { s.dataChan <- &msg } else { fmt.Println("Hash does not match") } case MsgAck: s.ackChan <- &msg } } } return err }
func NewFixedSizeUDPServer(maxMsgSize int, port int) (UDPServer, error) { addr, err := net.ResolveUDPAddr("udp4", fmt.Sprintf(":%v", port)) if err != nil { return nil, err } conn, err := net.ListenUDP("udp", addr) // non-blocking. no need to wait for any client to establish a connection like TCP does if err != nil { return nil, err } return &FixedSizeUDPServer{ maxMsgSize: maxMsgSize, addr: addr, conn: conn, closed: false, }, 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 }
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 }
// NewServer creates, initiates, and returns a new server. This function should // NOT block. Instead, it should spawn one or more goroutines (to handle things // like accepting incoming client connections, triggering epoch events at // fixed intervals, synchronizing events using a for-select loop like you saw in // project 0, etc.) and immediately return. It should return a non-nil error if // there was an error resolving or listening on the specified port number. func NewServer(port int, params *Params) (Server, error) { s := &server{ nextConnectId: 1, clients: make(map[int]*abstractClient), readFromClientChan: make(chan *msgPackage), writeToClientChan: make(chan *Message), readRequest: &requestRead{ ask: make(chan int), response: make(chan *Message), }, writeRequest: &requestWrite{ ask: make(chan []byte), connId: make(chan int), response: make(chan error), }, readList: list.New(), writeList: list.New(), flag: false, // variables for window size windowSize: params.WindowSize, mapNeedSend: list.New(), // variables for epoch epochChan: make(chan int), epochMillis: params.EpochMillis, epochLimit: params.EpochLimit, // close deleteClient: make(chan int), closeConnRequest: &requestCloseConn{ ask: 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), // close conn closeConn: make(chan int, 1), } // start server addr, err := lspnet.ResolveUDPAddr("udp", "localhost:"+strconv.Itoa(port)) if err != nil { return nil, err } conn, err := lspnet.ListenUDP("udp", addr) if err != nil { return nil, err } s.conn = conn go s.readMessage() go s.handleMessage() go s.epochFire() fmt.Println("new server") return s, nil }
// 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 }
// 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") }