123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361 |
- """Preliminary socket module.
-
- XXX Restrictions:
-
- - Only INET sockets
- - No asynchronous behavior
- - No socket options
- - Can't do a very good gethostbyaddr() right...
-
- """
-
- import java.net
- import org.python.core
- import jarray
- import string
-
- __all__ = ['AF_INET', 'SOCK_DGRAM', 'SOCK_RAW', 'SOCK_RDM', 'SOCK_SEQPACKET',
- 'SOCK_STREAM', 'SocketType', 'error', 'getfqdn', 'gethostbyaddr',
- 'gethostbyname', 'gethostname', 'socket']
-
- error = IOError
-
- AF_INET = 2
-
- SOCK_DGRAM = 1
- SOCK_STREAM = 2
- SOCK_RAW = 3 # not supported
- SOCK_RDM = 4 # not supported
- SOCK_SEQPACKET = 5 # not supported
- SOL_SOCKET = 0xFFFF
- SO_REUSEADDR = 4
-
- def _gethostbyaddr(name):
- # This is as close as I can get; at least the types are correct...
- addresses = java.net.InetAddress.getAllByName(gethostbyname(name))
- names = []
- addrs = []
- for addr in addresses:
- names.append(addr.getHostName())
- addrs.append(addr.getHostAddress())
- return (names, addrs)
-
- def getfqdn(name=None):
- """
- Return a fully qualified domain name for name. If name is omitted or empty
- it is interpreted as the local host. To find the fully qualified name,
- the hostname returned by gethostbyaddr() is checked, then aliases for the
- host, if available. The first name which includes a period is selected.
- In case no fully qualified domain name is available, the hostname is retur
- New in version 2.0.
- """
- if not name:
- name = gethostname()
- names, addrs = _gethostbyaddr(name)
- for a in names:
- if a.find(".") >= 0:
- return a
- return name
-
- def gethostname():
- return java.net.InetAddress.getLocalHost().getHostName()
-
- def gethostbyname(name):
- return java.net.InetAddress.getByName(name).getHostAddress()
-
- def gethostbyaddr(name):
- names, addrs = _gethostbyaddr(name)
- return (names[0], names, addrs)
-
-
- def socket(family, type, flags=0):
- assert family == AF_INET
- assert type in (SOCK_DGRAM, SOCK_STREAM)
- assert flags == 0
- if type == SOCK_STREAM:
- return _tcpsocket()
- else:
- return _udpsocket()
-
-
- class _tcpsocket:
-
- sock = None
- istream = None
- ostream = None
- addr = None
- server = 0
- file_count = 0
- reuse_addr = 0
-
- def bind(self, addr, port=None):
- if port is not None:
- addr = (addr, port)
- assert not self.sock
- assert not self.addr
- host, port = addr # format check
- self.addr = addr
-
- def listen(self, backlog=50):
- "This signifies a server socket"
- assert not self.sock
- self.server = 1
- if self.addr:
- host, port = self.addr
- else:
- host, port = "", 0
- if host:
- a = java.net.InetAddress.getByName(host)
- self.sock = java.net.ServerSocket(port, backlog, a)
- else:
- self.sock = java.net.ServerSocket(port, backlog)
- if hasattr(self.sock, "setReuseAddress"):
- self.sock.setReuseAddress(self.reuse_addr)
-
- def accept(self):
- "This signifies a server socket"
- if not self.sock:
- self.listen()
- assert self.server
- sock = self.sock.accept()
- host = sock.getInetAddress().getHostName()
- port = sock.getPort()
- conn = _tcpsocket()
- conn._setup(sock)
- return conn, (host, port)
-
- def connect(self, addr, port=None):
- "This signifies a client socket"
- if port is not None:
- addr = (addr, port)
- assert not self.sock
- host, port = addr
- if host == "":
- host = java.net.InetAddress.getLocalHost()
- self._setup(java.net.Socket(host, port))
-
- def _setup(self, sock):
- self.sock = sock
- if hasattr(self.sock, "setReuseAddress"):
- self.sock.setReuseAddress(self.reuse_addr)
- self.istream = sock.getInputStream()
- self.ostream = sock.getOutputStream()
-
- def recv(self, n):
- assert self.sock
- data = jarray.zeros(n, 'b')
- m = self.istream.read(data)
- if m <= 0:
- return ""
- if m < n:
- data = data[:m]
- return data.tostring()
-
- def send(self, s):
- assert self.sock
- n = len(s)
- self.ostream.write(s)
- return n
-
- def getsockname(self):
- if not self.sock:
- host, port = self.addr or ("", 0)
- host = java.net.InetAddress.getByName(host).getHostAddress()
- else:
- if self.server:
- host = self.sock.getInetAddress().getHostAddress()
- else:
- host = self.sock.getLocalAddress().getHostAddress()
- port = self.sock.getLocalPort()
- return (host, port)
-
- def getpeername(self):
- assert self.sock
- assert not self.server
- host = self.sock.getInetAddress().getHostAddress()
- port = self.sock.getPort()
- return (host, port)
-
- def setsockopt(self, level, optname, value):
- if optname == SO_REUSEADDR:
- self.reuse_addr = value
-
- def getsockopt(self, level, optname):
- if optname == SO_REUSEADDR:
- return self.reuse_addr
-
- def makefile(self, mode="r", bufsize=-1):
- file = None
- if self.istream:
- if self.ostream:
- file = org.python.core.PyFile(self.istream, self.ostream,
- "<socket>", mode)
- else:
- file = org.python.core.PyFile(self.istream, "<socket>", mode)
- elif self.ostream:
- file = org.python.core.PyFile(self.ostream, "<socket>", mode)
- else:
- raise IOError, "both istream and ostream have been shut down"
- if file:
- return _tcpsocket.FileWrapper(self, file)
-
- class FileWrapper:
- def __init__(self, socket, file):
- self.socket = socket
- self.sock = socket.sock
- self.istream = socket.istream
- self.ostream = socket.ostream
-
- self.file = file
- self.read = file.read
- self.readline = file.readline
- self.readlines = file.readlines
- self.write = file.write
- self.writelines = file.writelines
- self.flush = file.flush
- self.seek = file.seek
- self.tell = file.tell
-
- self.socket.file_count += 1
-
- def close(self):
- if self.file.closed:
- # Already closed
- return
-
- self.socket.file_count -= 1
- self.file.close()
-
- if self.socket.file_count == 0 and self.socket.sock == 0:
- # This is the last file Only close the socket and streams
- # if there are no outstanding files left.
- if self.sock:
- self.sock.close()
- if self.istream:
- self.istream.close()
- if self.ostream:
- self.ostream.close()
-
- def shutdown(self, how):
- assert how in (0, 1, 2)
- assert self.sock
- if how in (0, 2):
- self.istream = None
- if how in (1, 2):
- self.ostream = None
-
- def close(self):
- sock = self.sock
- istream = self.istream
- ostream = self.ostream
- self.sock = 0
- self.istream = 0
- self.ostream = 0
- # Only close the socket and streams if there are no
- # outstanding files left.
- if self.file_count == 0:
- if istream:
- istream.close()
- if ostream:
- ostream.close()
- if sock:
- sock.close()
-
-
- class _udpsocket:
-
- def __init__(self):
- self.sock = None
- self.addr = None
-
- def bind(self, addr, port=None):
- if port is not None:
- addr = (addr, port)
- assert not self.sock
- host, port = addr
- if host == "":
- self.sock = java.net.DatagramSocket(port)
- else:
- a = java.net.InetAddress.getByName(host)
- self.sock = java.net.DatagramSocket(port, a)
-
- def connect(self, addr, port=None):
- if port is not None:
- addr = (addr, port)
- host, port = addr # format check
- assert not self.addr
- if not self.sock:
- self.sock = java.net.DatagramSocket()
- self.addr = addr # convert host to InetAddress instance?
-
- def sendto(self, data, addr):
- n = len(data)
- if not self.sock:
- self.sock = java.net.DatagramSocket()
- host, port = addr
- bytes = jarray.array(map(ord, data), 'b')
- a = java.net.InetAddress.getByName(host)
- packet = java.net.DatagramPacket(bytes, n, a, port)
- self.sock.send(packet)
- return n
-
- def send(self, data):
- assert self.addr
- return self.sendto(self.addr)
-
- def recvfrom(self, n):
- assert self.sock
- bytes = jarray.zeros(n, 'b')
- packet = java.net.DatagramPacket(bytes, n)
- self.sock.receive(packet)
- host = packet.getAddress().getHostName()
- port = packet.getPort()
- m = packet.getLength()
- if m < n:
- bytes = bytes[:m]
- return bytes.tostring(), (host, port)
-
- def recv(self, n):
- assert self.sock
- bytes = jarray.zeros(n, 'b')
- packet = java.net.DatagramPacket(bytes, n)
- self.sock.receive(packet)
- m = packet.getLength()
- if m < n:
- bytes = bytes[:m]
- return bytes.tostring()
-
- def getsockname(self):
- assert self.sock
- host = self.sock.getLocalAddress().getHostName()
- port = self.sock.getLocalPort()
- return (host, port)
-
- def getpeername(self):
- assert self.sock
- host = self.sock.getInetAddress().getHostName()
- port = self.sock.getPort()
- return (host, port)
-
- def __del__(self):
- self.close()
-
- def close(self):
- sock = self.sock
- self.sock = 0
- sock.close()
-
- SocketType = _tcpsocket
-
- def test():
- s = socket(AF_INET, SOCK_STREAM)
- s.connect(("", 80))
- s.send("GET / HTTP/1.0\r\n\r\n")
- while 1:
- data = s.recv(2000)
- print data
- if not data:
- break
-
- if __name__ == '__main__':
- test()
|