2016-05-25 9 views
0

Ich habe ein einfaches Ruby-Skript, um Datei auf den Server/Web-App über TCP-Verbindung hochladen, aber es funktioniert nicht.Wenn ich das Skript ausführen geschieht nichts auf der Web-App/Serverseite. Der Server funktioniert gut, da ich versucht habe, Datei mit CURL hochzuladen, und es hochgeladen hat. Werfen Sie einen Blick auf meinen Code unten und lassen Sie mich wissen, was ich falsch mache. Ich verwende ruby ​​1.9.2-p290. Danke im Voraus.Einfache Ruby-TCP-Anfrage trifft den Server nicht

require 'socket' 

host = "myapp.herokuapp.com" 
port = 80 

client = TCPSocket.open(host, port) 

client.print("POST /api/binary HTTP/1.1\r\n") 
client.print("Host: myapp.herokuapp.com\r\n") 
client.print ("Accept: */* \r\n") 
client.print ("Content-Type: multipart/form-data;boundary=AaB03x \r\n") 


client.print("\n" + "AaB03x"+ "\n" "Content-Disposition: form-data; name='datafile'; filename='cam.jpg' \n Content-Type: image/jpeg \r\n") 
client.print ("\r\n") 
data = File.open("./pic.jpg", "rb") {|io| io.read} 
client.print (data) 
client.print ("\r\n") 
client.print("boundary=AaB03x\r\n") 

client.close 

IRB Konsole

>require 'socket' 
=> true 
> client = TCPSocket.open("myapp.herokuapp.com", 80) 
=> #<TCPSocket:fd 3> 
> client.print("GET /api/users HTTP/1.1") 
    => nil 
> client.print("POST /api/binary HTTP/1.1") 
    => nil 
+0

Bitte beachten Sie: '' print' verwendet write' intern, aber das Ergebnis nicht überprüft - dies bedeutet, dass ** dort alle keine Garantie gibt, werden die Daten ** gesendet werden. Je mehr auf Socket-Programmierung und erwägen, 'write' und' select' zu verwenden, um einen blockierenden Schreibvorgang zu emulieren, der blockiert, bis alle Daten gesendet wurden, oder eine ausgeglichene/threaded-Lösung zu verwenden, um alle Daten zu schreiben, die nicht das erste Mal geschrieben wurden . – Myst

+0

Wie ist dieses WebSocket verwandt? (Ich erinnere Sie daran, dass Websocket der Name eines Kommunikationsprotokolls ist, es ist kein Name für TCP/IP-Sockets) ... Bitte entfernen Sie das 'websocket'-Tag, wenn es nicht relevant ist. – Myst

Antwort

1

Sie müssen sicherstellen, dass Sie eine gültige HTTP-Anforderung senden.

  1. Sie benötigen einen Content-Length-Header. Das bedeutet, dass Sie den Körper im Voraus zusammenbauen müssen, damit Sie seine Länge für den Header bestimmen können, und senden Sie dann den Körper. Wenn Sie das falsch verstehen, blockiert der Server möglicherweise den Versuch, mehr Eingaben zu lesen, die nicht kommen.

  2. Ihre mehrteiligen Begrenzungen müssen repariert werden. Sie sollten mit -- beginnen, dann das Token aus der Kopfzeile: --AaB03x. Der letzte sollte mit -- auch enden: --AaB03x--. Stellen Sie sicher, dass in der Kopfzeile auch keine nachgestellten Leerzeichen enthalten sind, die Probleme verursachen können.

Einige andere Dinge, die wahrscheinlich die Anforderung nicht verhindern analysiert werden, aber Sie sollten bis ordentlich:

  1. Newlines in den Headern sollte \r\n nicht nur \n sein.

  2. Headerzeilen sollten vor ihnen keine Leerzeichen enthalten.

require 'socket' 

host = "myapp.herokuapp.com" 
port = 80 

client = TCPSocket.open(host, port) 

# Write out the headers. 
client.print("POST /api/binary HTTP/1.1\r\n") 
client.print("Host: myapp.herokuapp.com\r\n") 
client.print ("Accept: */* \r\n") 
# Note: no trailing whitespace. 
client.print ("Content-Type: multipart/form-data;boundary=AaB03x\r\n") 

# Assemble the body. 
# Note \r\n for all line endings, body doesn't start with newline. 
# Boundary marker starts with '--'. 
body = "--AaB03x\r\n" 
body << "Content-Disposition: form-data; name='datafile'; filename='cam.jpg'\r\n" 
# Header starts at left of line, no leading whitespace. 
body << "Content-Type: image/jpeg\r\n" 
body << "\r\n" 
data = File.open("./pic.jpg", "rb") {|io| io.read} 
body << data 
body << "\r\n" 
# Final boundary marker has trailing '--' 
body << "--AaB03x--\r\n" 

# Now we can write the Content-Length header, since 
# we now know the size of the body. 
client.print "Content-Length: #{body.bytesize}\r\n" 
# Blank line. 
client.print "\r\n" 
# Finally write out the body. 
client.print body 

# In reality you would want to parse the response from 
# the server before closing the socket. 
client.close 
+0

Yap.That funktioniert! Vielen Dank. – sparks

+0

In Betracht ziehen, die 'print'-Aufrufe zu minimieren, Schreiboperationen zu vereinheitlichen und den Schreibpuffer des Systems zu maximieren ... auch' print' verwendet 'write' intern, (' rb_io_write' nennt 'write'), aber doesn ' t Überprüfen Sie das Ergebnis - das bedeutet, dass einige der Daten möglicherweise aufgrund von System Socket Buffer-Limits nicht geschrieben werden **. Verwenden Sie 'write' und' select', um einen blockierenden Schreibvorgang zu emulieren, der blockiert wird, bis alle Daten gesendet wurden, oder verwenden Sie eine evented/threaded-Lösung, um mit dem Schreiben von Daten fortzufahren, die beim ersten Mal nicht geschrieben wurden. – Myst

Verwandte Themen