func (c *conn) sendWriteRequest(filename string, opts map[string]string) error {
	c.isSender = true
	c.tx.writeWriteReq(filename, c.mode, opts)
	for state := c.sendRequest; state != nil; {
		state = state()
	}
	return c.err
}
sendWriteRequest sends WRQ to server and negotiates transfer options
package tftp  
import (
	"bytes"
	"errors"
	"io"
	"net"
	"strconv"
	"time"
	"pack.ag/tftp/netascii"
)
const (
	defaultPort       = "69"
	defaultMode       = ModeOctet
	defaultUDPNet     = "udp"
	defaultTimeout    = time.Second
	defaultBlksize    = 512
	defaultWindowsize = 1
	defaultRetransmit = 10
)
var defaultOptions = map[string]string{
	optTransferSize: "0",  
}
func newConn(udpNet string, mode TransferMode, addr *net.UDPAddr) (*conn, error) {
	netConn, err := net.ListenUDP(udpNet, &net.UDPAddr{})
	if err != nil {
		return nil, wrapError(err, "network listen failed")
	}
	c := &conn{
		log:        newLogger(addr.String()),
		remoteAddr: addr,
		netConn:    netConn,
		blksize:    defaultBlksize,
		timeout:    defaultTimeout,
		windowsize: defaultWindowsize,
		retransmit: defaultRetransmit,
		mode:       mode,
	}
	c.rx.buf = make([]byte, 4+defaultBlksize)  
	return c, nil
}
func newSinglePortConn(addr *net.UDPAddr, mode TransferMode, netConn *net.UDPConn, reqChan chan []byte) *conn {
	return &conn{
		log:        newLogger(addr.String()),
		remoteAddr: addr,
		blksize:    defaultBlksize,
		timeout:    defaultTimeout,
		windowsize: defaultWindowsize,
		retransmit: defaultRetransmit,
		mode:       mode,
		buf:        make([]byte, 4+defaultBlksize),  
		reqChan:    reqChan,
		netConn:    netConn,
	}
}
func newConnFromHost(udpNet string, mode TransferMode, host string) (*conn, error) {
	addr, err := net.ResolveUDPAddr(udpNet, host)
	if err != nil {
		return nil, wrapError(err, "address resolve failed")
	}
	return newConn(udpNet, mode, addr)
}
type conn struct {
	log        *logger
	netConn    *net.UDPConn  
	remoteAddr net.Addr      
	reqChan chan []byte
	timer   *time.Timer
	isClient bool  
	isSender bool  
	blksize    uint16         
	timeout    time.Duration  
	windowsize uint16         
	mode       TransferMode   
	tsize      *int64         
	retransmit int  
	optionsParsed bool    
	window        uint16  
	block         uint16  
	catchup       bool    
	p             []byte  
	n             int     
	tries         int     
	err           error   
	closing       bool    
	done          bool    
	buf   []byte        
	txBuf *ringBuffer   
	rxBuf bytes.Buffer  
	tx datagram  
	rx datagram  
	reader io.Reader
	writer io.Writer
}