Wow, erst einmal möchte ich euch beiden ganz gewaltig danken, dass ihr euch die Zeit genommen habt so ausführlich auf die Fragestellung einzugehen. Ich entschuldige mich schon im Vorraus, falls die Fragen die ich Stelle arg naiv und blöd klingen mögen. Wie gesagt, ich bin, obwohl nicht ganz unerfahren, was Programmieren im Allgemeinen angeht, total neu bei Python. Allerdings gefällt mir die Sprache bisher außerordentlich gut.
@ Sirius3:
Danke für den Tipp mit der Main. Was genau meinst du mit Modul-Ebene? Ist das die Ebene, in der ich bisher meinen ganzen Code ausgeführt hatte? (Mir fehlte ja bisher eine Main-Methode.) Wenn ja, warum ist das architektonisch schöner?
Ja, die Verschachtelung ist echt problematisch und ich arbeite dran, da Sachen auszulagern.
Das mit dem kaputten recv habe ich glaube ich noch nicht ganz Verstanden. Ich habe jetzt eine vereinfachte Version erstellt, auf Basis dessen, was BlackJack geschrieben hat. (Danke, an dieser Stelle für die genommene Zeit und Mühe. Ich weiß das wirklich zu schätzen!)
Hier der Code:
Code: Alles auswählen
#!/usr/bin/env python
from __future__ import absolute_import, division, print_function
import sys
from contextlib import closing
from socket import AF_INET, error as SocketError, socket as Socket, SOCK_STREAM
from threading import Thread
HOST = '' # symbolic name meaning all available interfaces
PORT = 31337
def willAcceptMoreData(data):
if not '.' in data:
return True
else:
return false
def serve_client(connection):
with closing(connection):
connection.sendall('000\n')
while True:
data = connection.recv(1024)
if willAcceptMoreData(data):
reply = None
reply = data
print('client: ' + data)
assert reply is not None
connection.sendall(reply)
else:
break
def main():
with closing(Socket(AF_INET, SOCK_STREAM)) as server_socket:
try:
server_socket.bind((HOST, PORT))
except SocketError as error:
print('binding failed, code: {0[0]} message: {0[1]}'.format(error))
sys.exit(1)
server_socket.listen(10)
print('socket listening')
while True:
connection, address = server_socket.accept()
print('Connected with: {0[0]} : {0[1]}'.format(address))
thread = Thread(target=serve_client, args=(connection,))
thread.start()
if __name__ == '__main__':
main()
Die Kommunikation läuft jetzt folgendermaßen ab:
3-Way-Handshake, Eröffnung des Sockets:
Client: [SYN]
Server: [SYN, ACK]
Client: [ACK]
Mein Code:
Server: 000\n
Client: some command
Server: leeres Paket (auch als [ACK] = Acknowledgement geflagt)
Server: some command
Also, das Problem, nach dem ich fragte, ist damit leider bis hier noch nicht gelöst. :/
So nun @BlackJack:
Danke für den Tipp mit den Sternchenimporten - macht total Sinn sich nur das zu holen was man braucht.
Den Style Guide für Python werde ich mir, leider erst nach abschicken des Posts, zu Gemüte führen, danke dafür. Den Namen server_socket habe ich von dir übernommen. Ich bin teilweise sehr faul/gleichgültig was die Benennung von Variablen angeht, ist eine schlechte Angewohnheit.
Die + Schreibweise bin ich aus C++ gewohnt. Oft probiere ich bisher einfach aus, was ich schon von C++, Java, Objective C oder so kenne und freue mich wenn es klappt.
Auch sonst, vielen Dank für die Tipps zu Codekonventionen und unschönen Sachen, wie den Kommentaren. Die Faustregel zum Kommentar-Schreiben habe ich so noch nicht gehört, werde aber versuchen das so anzuwenden, die Erläuterung macht Sinn!
Ich glaube dem Abbrechen der Server-Schleife entspreche ich mit dem vereinfachten Code.
Eigentlich ist beabsichtigt, als Abbruchkriterium '000\n.000\n' zu verwenden. Allerdings funktionierte das bisher nicht, wenn ich es im Code an der Stelle des Punktes einsetze.
Abschließend muss ich leider gestehen, das ich nicht ganz offen war und möchte das jetzt berichtigen. Ihr helft mir aktuell bei einer Hausaufgabe für einen Kurs names "Application-Security". Ich mache im Moment ein Auslandssemester in New York and der NYU. Der Kurs hat eigentlich Graduate Standing und ist für Computer Science Absolventen. Ich bin in meinem 5ten Semester Medieninformatik in Deutschland, also nicht ganz so umfassend in Informatik ausgebildet, wie die anderen Kursteilnehmer, daher tu ich mich wahrscheinlich etwas schwerer als meine Kommilitonen. Der Professor gab uns folgendes Protokoll, dass wir, in welcher Sprache auch immer, implementieren sollten. Ich habe mich für Python entschieden, da dies eine Sprache war, die ich schon länger als interessant entdeckt hatte und ich hörte, dass gerade Socket Programming dort eine einfache Sache ist.
Ich hoffe mir sei das Vorenthalten des Protokolls verziehen, doch ich befürchtete, dass ich mit dem Argument, dass ich meine Hausaufgaben doch alleine lösen sollte, oder mich an die Schule wenden muss, abgewiesen worden wäre. (Wahrscheinlich Irrsinn?!)
Anyway, hier das vorenthaltene Protokoll:
Code: Alles auswählen
CS 9163 Working Group M. Bentz
Matt Declared Protocol: 0001 NYU
Sep 2014
Arbitrary Storage Protocol (ASP) v1
Status of this Memo
This document specifies a protocol for CS9163 students to implement. Please
refer to the author for the most current edition of this document. Distribution
is unlimited.
1. Overview
It is often nice to be able to store arbitrary data on a remote host. This
statement is exceedingly vague and based on unquestioned assumptions.
Fortunately, the protocol herein described has no real purpose in the world
other than to provide a teachable experience to students in CS9163.
2. Basic Functionality
The protocol supports the storage and retrieval of arbitrary data for the
duration of a network session. Information exchange between the client and
server are handled in a one-to-one fashion, i.e. each request by the client is
met with a response from the server. These requests are handled by presenting
access methods to the server. The server will respond with a response code
which indicates that the client should proceed, the method was a success, or an
error occurred.
The two basic methods GET and PUT store and retrieve those data associated with
a given key. A type may be associated with each key. There is no guarantee
that data will survive close of the connection. The CLEAR method clears a key.
The QUIT method closes the session.
3. Methods
3.1 The PUT Method
The PUT method is the means by which a client requests data of an indicated
length (indicated in decimal integer bytes) be stored by the server under the
supplied key:
"PUT" <space> <length> <space> <key> <newline>
The server will respond with one of the following codes:
Proceed, Unknown Error, Length Error, Key Error
Upon receipt of the Proceed code, the client will send its data. The completion
of this sent data will be indicated by <newline> <period> <newline>, i.e. a
period on its own line. The server will associate as many bytes of this data as
specified in the method's length. Superfluous bytes are ignored. An
under-supply of data will cause a Length Error to result. A successful store
will result in a Ready code.
3.2 The GET Method
The GET method is the means by which a client requests data associated with the
supplied key to be returned:
"GET" <space> <length> <space> <key> <newline>
The server will respond with either the requested data and a Ready code or an
error code. On success, the server immediately begins sending the data
associated with the supplied key up to the given length in bytes. Upon
completion, it appends a <newline> to the data and sends a Ready code.
In the event of an error, the server may respond with one of the following
codes:
Unknown Error, Length Error, Key Error
3.3 The CLEAR Method
The CLEAR method removes a key and its associated data from the server's
consideration. It is specified as follows:
"CLEAR" <space> <key> <newline>
And may return one of the following codes:
Ready, Unknown Error, Key Error
3.4 The QUIT Method
The QUIT method requests that the connection to the server be terminated. It
results in no response code.
4. Response Codes
Response codes are numeric indicators of direction, information, success, and
failure. All codes are sent with an immediately following newline. They are as
follows:
4.1. Ready ("000")
The server is ready to accept the next request.
4.2. Proceed ("001")
The server is ready to receive your information.
4.3. Unknown Error ("100")
An unknown error has occurred.
4.4. Length Error ("101")
The method length is incorrect. For a PUT method, the server may be unable to
store that amount of data. For A GET method, the client may have requested more
bytes than were stored with that key.
4.5. Key Error ("102")
There is a problem with the key. For a PUT method, the key is already present
and thereby in collision. For a GET or CLEAR method, the key does not exist.
5. Example Sequence
The following is an example session between client and server. Server sent
information is prepended by S: and client send information by C:
S: 000
C: PUT 13 foo
S: 001
C: Hello, world!
C: .
S: 000
C: PUT 8 bar
S: 001
C: Rutabaga!
C: .
S: 000
C: FEED dog
S: 100
C: GET 8 bar
S: Rutabaga
S: 000
C: CLEAR foo
S: 000
C: CLEAR foo
S: 102
C: PUT 8 foo
S: 001
C: I am new data in foo!
C: .
S: 000
C: GET 12 foo
S: 101
C: QUIT
6. ABNF Definitions
<space> = %x20 ; sp
<newline> = %x0a ; nl
<period> = %x2e ; .
<key> = ALPHA / DIGIT
<length> = DIGIT
7. References
D. Crocker, "Augmented BNF for Syntax Specifications: ABNF", STD 68, RFC 5234,
Brandenburg InternetWorking, January 2008