I'm implementing chat with html5 web sockets in go lang and having errors both at client and server end.
Client Error:
WebSocket connectiont to 'ws://192.168.16.90:4000` failed: Invalid HTTP version string GET
Server Error:
continous looping of the following log message in the terminal,
connection closed\n received message:\n message sent:\n
Server Code:
func (s *Service) InitializeService() {
listener, err := net.Listen("tcp", ":4000")
if err != nil {
log.Fatal(err)
}
log.Println("Chat server started to listen on port ", listener.Addr())
defer listener.Close()
for {
conn, err := listener.Accept()
if err != nil {
log.Fatal(err)
}
fmt.Println("A new connection accepted.")
go listenConnection(conn)
}
}
func listenConnection(conn net.Conn) {
for {
buffer := make([]byte, 1400)
dataSize, err := conn.Read(buffer)
if err != nil {
fmt.Println("connection closed")
}
data := buffer[:dataSize]
fmt.Println("received message: ", string(data))
_, err = conn.Write(data)
if err != nil {
log.Fatalln(err)
}
fmt.Println("message sent: ", string(data))
}
}
Client Code:
var connection = new WebSocket("ws://192.168.16.90:4000");
connection.onopen = function() {
console.log("onopen");
connection.send("Ping");
};
connection.onerror = function(error) {
console.log("WebSocket Error", error);
};
connection.onmessage = function(e) {
console.log("Server: ", e.data);
};
Related
I am trying to build a HTTPS proxy But i get PR_END_OF_FILE_ERROR in firefox that means failed to create a secure connection because no cipher suit found (more description).
What I do is after receiving CONNECT header from browser, I make a socket to that host, Connect successfully, and then write HTTP/1.1 200 Connection Established\r\n\r\n to broswer and then just pipe each other. It works OK on some host like google but not on blocked host (in my country) like youtube. I even changed DNS to 8.8.8.8 (google) but still doesn't work. I think that browser tries to get something out of proxy but don't know what or how.
func main() {
ln, _ := net.Listen("tcp", ":"+jjConfig.ListenPort)
for {
conn, _ := ln.Accept()
err = conn.SetDeadline(time.Time{})
if err != nil {
fmt.Println(err)
return
}
fmt.Println("Connection Received")
go handleSocket(conn)
}
}
func handleSocket(client_to_proxy net.Conn) {
buffer := make([]byte, 9*1024)
length, err := bufio.NewReader(client_to_proxy).Read(buffer)
if err != nil {
fmt.Println("ERR1 ", err)
return
}
message := processReceived(buffer, length, jjConfig.ListenAuthentication, jjConfig.ListenUsers,
jjConfig.ListenEncryption, jjConfig.ListenEncryptionKey)
if message == "" {
return
}
fmt.Println("MESSAGE IS: " + message)
var host []string
headers := strings.Split(message, "\r\n")
for _, header := range headers {
if strings.HasPrefix(header, "Host") {
host = strings.Split(header, " ")
fmt.Println("HOST ISSSSSSSS:" + host[1])
break
}
}
if strings.HasSuffix(host[1], "443") {
proxy_to_server, e := net.Dial("tcp", host[1])
if e != nil {
fmt.Println("ERROR3 ", e)
return
}
fmt.Println("CONNECTED TO: " + host[1])
Writelength, err := client_to_proxy.Write([]byte("HTTP/1.1 200 Connection Established\r\n\r\n"))
if err != nil {
return
}
fmt.Println("WROTE 200 OK: " + strconv.Itoa(Writelength))
if e != nil {
fmt.Println("ERROR4 ", e)
return
}
go exchange(client_to_proxy, proxy_to_server, host[1])
exchange(proxy_to_server, client_to_proxy, host[1])
} else {
proxy_to_server, e := net.Dial("tcp", host[1]+":80")
if e != nil {
fmt.Println("ERROR5 ", e)
return
}
Writelength, e := proxy_to_server.Write([]byte(message))
fmt.Println("WROTE 80 Header: " + strconv.Itoa(Writelength))
if e != nil {
fmt.Println("ERROR6 ", e)
return
}
go exchange(proxy_to_server, client_to_proxy, host[1])
exchange(client_to_proxy, proxy_to_server, host[1])
}
}
func exchange(src, dest net.Conn, host string) {
defer func(src net.Conn) {
err := src.Close()
if err != nil {
fmt.Println("ERRCPP2 ", err)
}
}(src)
defer func(dest net.Conn) {
err := dest.Close()
if err != nil {
fmt.Println("ERRCPP1 ", err)
}
}(dest)
written, err := io.Copy(src, dest)
if err != nil {
fmt.Println("COPY ERROR SERVER IS "+host+": ", written, err)
return
}
}
I use high-level structures to create a ws server.
func wsHandler(w http.ResponseWriter, r *http.Request) {
re := regexp.MustCompile(`^\/ws\/([0-9a-zA-Z]+)\/*`)
match := re.FindStringSubmatch(r.URL.Path)
if len(match) != 2 {
http.NotFound(w, r)
return
}
conn, _, _, err := ws.UpgradeHTTP(r, w)
if err != nil {
log.Printf("gobwas/ws: %s", err)
}
go func() {
defer conn.Close()
channels.Lock()
channels.Channels[match[1]] = append(channels.Channels[match[1]], &conn)
channels.Unlock()
for {
msg, op, err := wsutil.ReadClientData(conn)
if err != nil {
if err != io.EOF {
log.Printf("gobwas/ws/wsutil: %s", err)
}
break
}
if len(msg) > 0 {
go sendMessage(&conn, op, match[1], msg)
}
}
deleteConn(&conn, match[1])
}()
}
Then, when I implement a graceful disconnection, then with the usual conn.Close (), the connection simply breaks outside the protocol. I use the following code to close:
func onShutdown() {
channels.RLock()
for _, channel := range channels.Channels {
for _, conn := range channel {
if err := ws.WriteFrame(*conn, ws.NewCloseFrame(ws.NewCloseFrameBody(ws.StatusNormalClosure, "Server shutdown"))); err != nil {
fmt.Println(err)
}
(*conn).Close()
}
}
channels.RUnlock()
}
And even if I wait for a response from the client and then close the connection, then anyway, the client fixes the disconnection. (The client is the browser and JS WebSocket).
Sample JS code:
var socket = new WebSocket(`${location.protocol === "https:" ? "wss:" : "ws:"}//${window.location.host}/ws/valid`);
socket.onclose = function (event) {
if (event.wasClean) {
console.log('Clean');
} else {
console.log('disconnect');
}
console.log('Code: ' + event.code + ' reason: ' + event.reason);
};
I have an Go routine running a concurrent TCP 4 server, but everytime I connect to it from via Dial, the TCP server throws an error saying only "EOF". Interestingly it is processing the first line of data, but then the connection handle throws the error.
tcp server instance:
if err != nil {
fmt.Println("an error occured: ")
fmt.Println(err)
return
}
defer l.Close()
for {
conn, err_handle := l.Accept()
if err_handle != nil {
fmt.Println("node err: ",err_handle)
return
}
go handle_Connection(conn, topics)
}
handle_Connection:
func handle_Connection(conn net.Conn, topics map[string][]string) {
defer conn.Close()
fmt.Println("client connected")
for {
data, err_handle := bufio.NewReader(conn).ReadString('\n')
if err_handle != nil {
fmt.Println("Err: ", err_handle)
return
}
client:
conn, err := net.Dial("tcp4", ":"+strconv.Itoa(port))
if err != nil {
fmt.Println("an error occured: ")
fmt.Println(err)
}
The very simple fix to the problem is that the server bufio data reader is declared in the loop which is processing the data.
func handle_Connection(conn net.Conn, topics map[string][]string) {
defer conn.Close()
fmt.Println("client connected")
for {
data, err_handle := bufio.NewReader(conn).ReadString('\n')
if err_handle != nil {
fmt.Println("Err: ", err_handle)
return
}
should be:
func handle_Connection(conn net.Conn, topics map[string][]string) {
defer conn.Close()
fmt.Println("client connected")
data, err_handle := bufio.NewReader(conn).ReadString('\n')
for {
if err_handle != nil {
fmt.Println("Err: ", err_handle)
return
}
I want to test the restart connection to the rabbitmq server.
On wrote small script to test.
http://play.golang.org/p/l3ZWzG0Qqb
But it's not working.
In step 10, I close the channel and connection. And open them again. And re-create chan amqp.Confirmation ( :75) . And continue the cycle.
But after that, from the chan confirms nothing return.
UPD: code here.
package main
import (
"fmt"
"github.com/streadway/amqp"
"log"
"os"
"time"
)
const SERVER = "amqp://user:pass#localhost:5672/"
const EXCHANGE_NAME = "publisher.test.1"
const EXCHANGE_TYPE = "direct"
const ROUTING_KEY = "publisher.test"
var Connection *amqp.Connection
var Channel *amqp.Channel
func setup(url string) (*amqp.Connection, *amqp.Channel, error) {
conn, err := amqp.Dial(url)
if err != nil {
return nil, nil, err
}
ch, err := conn.Channel()
if err != nil {
return nil, nil, err
}
return conn, ch, nil
}
func main() {
url := SERVER
Connection, Channel, err := setup(url)
if err != nil {
fmt.Println("err publisher setup:", err)
return
}
confirms := Channel.NotifyPublish(make(chan amqp.Confirmation, 1))
if err := Channel.Confirm(false); err != nil {
log.Fatalf("confirm.select destination: %s", err)
}
for i := 1; i <= 3000000; i++ {
log.Println(i)
if err != nil {
fmt.Println("err consume:", err)
return
}
if err := Channel.Publish(EXCHANGE_NAME, ROUTING_KEY, false, false, amqp.Publishing{
Body: []byte(fmt.Sprintf("%d", i)),
}); err != nil {
fmt.Println("err publish:", err)
log.Printf("%+v", err)
os.Exit(1)
return
}
// only ack the source delivery when the destination acks the publishing
confirmed := <-confirms
if confirmed.Ack {
log.Printf("confirmed delivery with delivery tag: %d", confirmed.DeliveryTag)
} else {
log.Printf("failed delivery of delivery tag: %d", confirmed.DeliveryTag)
// TODO. Reconnect will be here
}
if i == 10 {
Channel.Close()
Connection.Close()
while := true
for while {
log.Println("while")
time.Sleep(time.Second * 1)
Connection, Channel, err = setup(url)
if err == nil {
while = false
confirms = Channel.NotifyPublish(make(chan amqp.Confirmation, 1))
log.Printf("%+v", confirms)
}
}
}
time.Sleep(time.Millisecond * 300)
}
os.Exit(1)
}
You should put channel in confirm mode. by calling the channel.Confirm() method.
After closing the connection and even after getting new channel on the same connection, you should call Confirm() method again, since the channel is different from the old channel, and the default for all new channel is not to send confirm.
These days I was working on send message via websoket,using Beego framework.
but meet the wrong message http: multiple response.WriteHeader calls
Where is the problem?
Any tips would be great!
func (this *WsController) Get() {
fmt.Println("connected")
handler(this.Ctx.ResponseWriter, this.Ctx.Request, this);
conn, err := upgrader.Upgrade(this.Ctx.ResponseWriter, this.Ctx.Request, nil)
if _, ok := err.(websocket.HandshakeError); ok {
http.Error(this.Ctx.ResponseWriter, "Not a websocket handshake", 400)
return
} else if err != nil {
return
}
fmt.Println("connected")
connection := consumer.New(beego.AppConfig.String("LoggregatorAddress"), &tls.Config{InsecureSkipVerify: true}, nil)
fmt.Println("===== Tailing messages")
msgChan, err := connection.Tail(this.Ctx.Input.Param(":appGuid"), this.Ctx.Input.Param(":token"))
if err != nil {
fmt.Printf("===== Error tailing: %v\n", err)
} else {
for msg := range msgChan {
// if closeRealTimeLogFlag{
// consumer.Close()
// break
// }
if err = conn.WriteMessage(websocket.TextMessage, msg.Message); err != nil {
fmt.Println(err)
}
fmt.Printf("%v \n", msg)
}
}
}
because you write more than statusCode