Google Groups no longer supports new Usenet posts or subscriptions. Historical content remains viewable.
Dismiss

Sockets: code works locally but fails over LAN

6 views
Skip to first unread message

n00m

unread,
Aug 31, 2005, 9:03:00 AM8/31/05
to
import socket, thread
host, port = '192.168.0.3', 1434
s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.connect((host, 1433))
s1.bind((host, port))
s1.listen(1)
cn, addr = s1.accept()

def VB_SCRIPT():
while 1:
data = cn.recv(4096)
if not data: return
s2.send(data)
print 'VB_SCRIPT:' + data + '\n\n'

def SQL_SERVER():
while 1:
data = s2.recv(4096)
if not data: return
cn.send(data)
print 'SQL_SERVER:' + data + '\n\n'

thread.start_new_thread(VB_SCRIPT,())
thread.start_new_thread(SQL_SERVER,())

=============================================

The above code acts as an intermediator between a very simple VB script
and SQL Server. Like follows:
the vbs sends its requests to "fake" port 1434 and the python code
catches and re-sends them to sql server which listens to its DEFAULT
port = 1433... And vice versa.


=========================================================
VB script:
=========================================================

Set cn = CreateObject("ADODB.Connection")
cn.Open _
"Provider=sqloledb;Data Source=192.168.0.3,1434;" & _
"Network Library=DBMSSOCN;Initial Catalog=pubs;" & _
"User ID=qwe;Password=asdasd;"

cn.Execute "select * from authors;"
cn.Close
Set cn = Nothing

=========================================================


It works fine (I see all client/server data printed in IDLE window)but
only locally. I.e. if vbs, python and sql server run on the same
machine.

If I run the vbs from some other machine in my LAN then it fails to
work out properly. Below is all that vbs and sql server are able to say
to each other:


===========================================================

VB_SCRIPT:
SERVER qwe asdasd 000000a5 Р·€Ut
Microsoft (r) W 192.168.0.3,1434 asdasd
OLEDB

SQL_SERVER:
Щ 3 г
pubs master«0 E # Changed database context
to 'pubs'. W г

us_english «4 G ' Changed language setting to us_english. W г
cp1251 ­ Microsoft SQL Server _ Вг 4096 4096э


VB_SCRIPT:
G 4096

==========================================================


In abt 30 seconds OLE DB Provider (on the vbs side) reports "General
Network Error".


PEOPLE, WHY ON THE EARTH IT DOES NOT WORK OVER LAN ???

PS:
Of course, without involving Python into the process vbs and sql server
communicate with each other just fine - no matter locally or over LAN;
on win2k machines or on/from NT 4.0 machine.

Peter Hansen

unread,
Aug 31, 2005, 9:13:39 AM8/31/05
to
n00m wrote:
> import socket, thread
> host, port = '192.168.0.3', 1434
> s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
> s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
> s2.connect((host, 1433))
> s1.bind((host, port))
> s1.listen(1)
> cn, addr = s1.accept()
>
> def VB_SCRIPT():
> while 1:
> data = cn.recv(4096)
> if not data: return
> s2.send(data)
> print 'VB_SCRIPT:' + data + '\n\n'
>
> def SQL_SERVER():
> while 1:
> data = s2.recv(4096)
> if not data: return
> cn.send(data)
> print 'SQL_SERVER:' + data + '\n\n'

Several suggestions:

1. Use repr(data) instead of just 'data' above, to see better the actual
bytes without the possibility of control characters like \r and \b
screwing things up.

2. I'm not at all sure that accessing the same socket object
simultaneously from two threads is safe. You might consider creating a
pair of Queue objects to safely communicate the information between the
two threads. That, of course, poses the problem of how do you wait on
data to arrive from the socket and from the Queue at the same time. One
approach is to use non-blocking sockets or timeouts, while the other is
to use a pre-existing asynchronous framework such as, say, Twisted, and
avoid reinventing the wheel (and making all the same mistakes that other
programmers have made zillions of times before you).

It's also possible this is not remotely related to your problem, but I
suspect without knowing more about SQL Server, VB, and your own setup
I'd be guessing wildly anyway...

-Peter

Grant Edwards

unread,
Aug 31, 2005, 9:42:25 AM8/31/05
to
On 2005-08-31, Peter Hansen <pe...@engcorp.com> wrote:

> 2. I'm not at all sure that accessing the same socket object
> simultaneously from two threads is safe.

It's OK under Unix. Having one thread handle rx and a
different one handle tx is a pretty widely used method.

Don't know about Win32...


--
Grant Edwards grante Yow! Someone in DAYTON,
at Ohio is selling USED
visi.com CARPETS to a SERBO-CROATIAN

Jp Calderone

unread,
Aug 31, 2005, 10:51:08 AM8/31/05
to twisted...@twistedmatrix.com
On 31 Aug 2005 06:03:00 -0700, n00m <n0...@narod.ru> wrote:
>import socket, thread
>host, port = '192.168.0.3', 1434
>s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
>s2.connect((host, 1433))
>s1.bind((host, port))
>s1.listen(1)
>cn, addr = s1.accept()
>
>def VB_SCRIPT():
> while 1:
> data = cn.recv(4096)
> if not data: return
> s2.send(data)
> print 'VB_SCRIPT:' + data + '\n\n'
>
>def SQL_SERVER():
> while 1:
> data = s2.recv(4096)
> if not data: return
> cn.send(data)
> print 'SQL_SERVER:' + data + '\n\n'
>
>thread.start_new_thread(VB_SCRIPT,())
>thread.start_new_thread(SQL_SERVER,())

This is about the same as:

mktap portforward --port 1434 --host 192.168.0.3 --dest_port 1433
twistd -f portforward.tap

You'll find the code behind these two commands here:

<http://cvs.twistedmatrix.com/cvs/trunk/twisted/tap/portforward.py?view=markup&rev=13278>

and here:

<http://cvs.twistedmatrix.com/cvs/trunk/twisted/protocols/portforward.py?view=markup&rev=12914>

And of course, the main Twisted site is <http://twistedmatrix.com/>.

Some differences between portforward.tap and your code include:

portforward.tap will accept multiple connections, rather than just one. portforward.tap won't print out all the bytes it receives (I assume this is just for debugging purposes anyway - if not, a simple modification will cause it to do this). portforward.tap won't non-deterministically drop traffic, since Twisted checks the return value of send() and properly re-transmits anything which has not actually been sent.

Hope this helps,

Jp

n00m

unread,
Aug 31, 2005, 1:43:01 PM8/31/05
to
Thank you all for your replies!
1.
repr() is not what I need (currently).
I'd better like to see the pure text of "talkings" between VBS and SQL
Server.
2.
Jp, thank you very much for the links!
I just oblige to test this Twisted stuff, but I'm afraid it's a bit
above my head
so far.
And, frankly speaking, above all I'd like to understand why my code
only works
locally... I wish it did not work AT ALL. Sure you understand what I
mean. :)

Bryan Olson

unread,
Aug 31, 2005, 4:15:17 PM8/31/05
to
Grant Edwards wrote:

> Peter Hansen wrote:
>
>
>>2. I'm not at all sure that accessing the same socket object
>>simultaneously from two threads is safe.
>
> It's OK under Unix. Having one thread handle rx and a
> different one handle tx is a pretty widely used method.
>
> Don't know about Win32...

A thread for send and one for recv is also frequently used with
Winsock. Can anyone vouch for the Python wrapping?


--
--Bryan

Grant Edwards

unread,
Aug 31, 2005, 4:31:57 PM8/31/05
to
On 2005-08-31, Bryan Olson <fakea...@nowhere.org> wrote:

>>>2. I'm not at all sure that accessing the same socket object
>>>simultaneously from two threads is safe.
>>
>> It's OK under Unix. Having one thread handle rx and a
>> different one handle tx is a pretty widely used method.
>>
>> Don't know about Win32...
>
> A thread for send and one for recv is also frequently used
> with Winsock. Can anyone vouch for the Python wrapping?

The last time I looked, it was a pretty thin wrapper, and
shouldn't cause a problem. I just looked at 2.3.5 sources. [I
think the timeout feature is new since I hacked on socketmodule.c
last.] I don't really see anything troublesome.

Basically, socket.recv() just calls recv() and socket.send()
just calls send().

--
Grant Edwards grante Yow! MY income is ALL
at disposable!
visi.com

Bryan Olson

unread,
Aug 31, 2005, 5:03:19 PM8/31/05
to

n00m wrote:
> import socket, thread
> host, port = '192.168.0.3', 1434

Consider using INADDR_ANY instead of the specific host IP
address. The empty string will resolve to INADDR_ANY if passed
as the host to bind(). (Though that's not the problem.)

> s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
> s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
> s2.connect((host, 1433))
> s1.bind((host, port))
> s1.listen(1)
> cn, addr = s1.accept()

You probably want the the accept() in a loop.


> def VB_SCRIPT():
> while 1:
> data = cn.recv(4096)
> if not data: return
> s2.send(data)

Use sendall(), not send().

> print 'VB_SCRIPT:' + data + '\n\n'
>
> def SQL_SERVER():
> while 1:
> data = s2.recv(4096)
> if not data: return
> cn.send(data)

As above, use sendall().

> print 'SQL_SERVER:' + data + '\n\n'
>
> thread.start_new_thread(VB_SCRIPT,())
> thread.start_new_thread(SQL_SERVER,())
>
> =============================================
>
> The above code acts as an intermediator between a very simple VB script
> and SQL Server. Like follows:
> the vbs sends its requests to "fake" port 1434 and the python code
> catches and re-sends them to sql server which listens to its DEFAULT
> port = 1433... And vice versa.

[...]


> It works fine (I see all client/server data printed in IDLE window)but
> only locally. I.e. if vbs, python and sql server run on the same
> machine.

[...]


My first two guess are:

The client is trying to make more than one connection.
Putting accept in a loop and moving some stuff will support
that.

The send() call is not sending all the data. Using sendall()
should fix that.


Try the following, but *not in Idle*. The code doesn't yet have
a clean stopping method, and the run-on threads will screw-up
Idle.

import socket, thread

sqls_host, sqls_port = '192.168.0.3', 1443
proxy_host, proxy_port = '', 1434

# How I tested it:
# sqls_host, sqls_port = 'www.google.com', 80


def VB_SCRIPT():
while 1:
data = cn.recv(4096)
if not data: return

s2.sendall(data)


print 'VB_SCRIPT:' + data + '\n\n'

def SQL_SERVER():
while 1:
data = s2.recv(4096)
if not data: return

cn.sendall(data)


print 'SQL_SERVER:' + data + '\n\n'


s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind((proxy_host, proxy_port))
s1.listen(5)

while 1:
cn, addr = s1.accept()
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.connect((sqls_host, sqls_port))
thread.start_new_thread(VB_SCRIPT,())
thread.start_new_thread(SQL_SERVER,())


--
--Bryan

Message has been deleted

Fredrik Lundh

unread,
Aug 31, 2005, 9:14:24 AM8/31/05
to pytho...@python.org
"n00m" <n0...@narod.ru> wrote:

> PEOPLE, WHY ON THE EARTH IT DOES NOT WORK OVER LAN ???

what happens if you change

s1.bind((host, port))

to

s1.bind(("", port))

?

</F>

John Hazen

unread,
Aug 31, 2005, 3:51:02 PM8/31/05
to n00m, pytho...@python.org
* n00m <n0...@narod.ru> [2005-08-31 05:45]:

> import socket, thread
> host, port = '192.168.0.3', 1434
> s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
> s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
> s2.connect((host, 1433))
> s1.bind((host, port))

I think the problem is that you're using the same host for both the send
and recieve sockets. Wouldn't you want one host to be the localhost,
and one to be sql server?

If it doesn't work even when only the VBscript is on a different box,
are you running an OS with a firewall that you have to disable?

-John

n00m

unread,
Sep 1, 2005, 1:51:32 PM9/1/05
to
>Bryan;
I tested your code locally (in I*D*L*E) - it works fine!
And of course I'll test it over LAN but only tomorrow - at work.
See the picture of my IDLE window with output of your code:
http://free.7host02.com/n00b/socket_Br.gif
Note the 4th line in Blue: there Z is the name of my home machine,
qwe is the login name (from VBS(ADO) connection string) and right
after "qwe" - this login's password ("asdasd") but it's encrypted
by oledb provider.


>Dennis;
I understand pretty well what you mean. Thank you for the repr().


>Fredrik;
Locally it works! The rest - tomorrow.


>John;
How exactly should I "correct" the code?

Bryan Olson

unread,
Sep 2, 2005, 12:06:08 AM9/2/05
to
n00m wrote:
>>Bryan;
>
> I tested your code locally (in I*D*L*E) - it works fine!

Glad it worked, but I'd still disrecommend IDLE for that
version. Threads may live after the program seems to be done
(and may still own the port you need). Below is a version that
respects ^C to terminate more-or-less cleanly.

> And of course I'll test it over LAN but only tomorrow - at work.
> See the picture of my IDLE window with output of your code:
> http://free.7host02.com/n00b/socket_Br.gif

I didn't touch the printing, so it should output the same thing
as your version. Looks like you've got some UTF-16 action there,
and Python may be able to print it nicer if you use the
unicode/codec stuff.


--
--Bryan


import socket, threading, select

sqls_host, sqls_port = '192.168.0.3', 1443
proxy_host, proxy_port = '', 1434


def start_deamon_thread(func, args):
""" Run func(*args) in a deamon thread.
"""
thread = threading.Thread(target=func, args=args)
thread.setDaemon(True)
thread.start()


def sock_copy(s_from, s_to, annotation):
while 1:
data = s_from.recv(4096)
if not data:
break
s_to.sendall(data)
print annotation + data + '\n\n'


s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind((proxy_host, proxy_port))
s1.listen(5)

while 1:
s, _, _ = select.select([s1], [], [], 1.0)
if s:
cn, _ = s1.accept()


s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.connect((sqls_host, sqls_port))

start_deamon_thread(sock_copy, (cn, s2, 'VB_SCRIPT:'))
start_deamon_thread(sock_copy, (s2, cn, 'SQL_SERVER:'))

Message has been deleted

Bryan Olson

unread,
Sep 2, 2005, 12:20:22 PM9/2/05
to
I wrote:
> Below is a version that respects ^C to terminate
> more-or-less cleanly.

Oops, one more bug^H^H^H improvement. I forgot to shutdown
writing.


> import socket, threading, select
>
> sqls_host, sqls_port = '192.168.0.3', 1443
> proxy_host, proxy_port = '', 1434
>
>
> def start_deamon_thread(func, args):
> """ Run func(*args) in a deamon thread.
> """
> thread = threading.Thread(target=func, args=args)
> thread.setDaemon(True)
> thread.start()
>
>
> def sock_copy(s_from, s_to, annotation):
> while 1:
> data = s_from.recv(4096)
> if not data:

Insert:
| s_to.shutdown(socket.SHUT_WR)

> break
> s_to.sendall(data)
> print annotation + data + '\n\n'
>
>
> s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
> s1.bind((proxy_host, proxy_port))
> s1.listen(5)
>
> while 1:
> s, _, _ = select.select([s1], [], [], 1.0)
> if s:
> cn, _ = s1.accept()
> s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
> s2.connect((sqls_host, sqls_port))
> start_deamon_thread(sock_copy, (cn, s2, 'VB_SCRIPT:'))
> start_deamon_thread(sock_copy, (s2, cn, 'SQL_SERVER:'))


--
--Bryan

n00m

unread,
Sep 2, 2005, 1:21:03 PM9/2/05
to
My today's tests (over LAN).
I think *it* will drive me mad very soon.

Firstly I tested both Bryan's codes. And they worked fine!
Just as if they were tested locally!

Then I tested Fredrik suggestion. And it worked out too.
Expect unexpected, - as they say.

At last I decided to test my own version (just for the
experiment's purity). And... pfffff... it worked OK!

What happened to those machines over the night?
NOTHING! Nobody can access them but me.

Then I decided to test it from other ("the third") machine.
And again both Bryan's codes worked out like champs.
But my own ... failed! (as usually)!

Then I ran the vbs from the 4th machine...
Bryan's and *mine* worked OK...


Bryan wrote:
> The client is trying to make more than one connection.

I don't think so. Look at the very first line of the vbs:

Set cn = CreateObject("ADODB.Connection")

Create .Connection! NOT .Connections.

> Glad it worked, but I'd still disrecommend IDLE...
But it does NOT work without IDLE!

PS:


> Oops, one more bug^H^H^H improvement.
> I forgot to shutdown writing.

LOL Thank you! But while I don't understand what's going on
with the core part of the code this improvement doesn't much
matter.

Bryan Olson

unread,
Sep 2, 2005, 6:16:21 PM9/2/05
to
n00m wrote:
> My today's tests (over LAN).
> I think *it* will drive me mad very soon.

<Conflicting results snipped>

Network programming is like that. Just because something worked
once doesn't mean it really works. I had guessed two causes for
the behavior you were seeing, and either could result in sporadic
failures.

> Bryan wrote:
>
>>The client is trying to make more than one connection.
>
> I don't think so. Look at the very first line of the vbs:
>
> Set cn = CreateObject("ADODB.Connection")
>
> Create .Connection! NOT .Connections.

An ADODB connection is not the same as a TCP connection; unless
you have a documented promise, don't expect them to map one-to-
one. I don't know much about ADODB, but it's perfectly normal in
network programming to run multiple logical connections over one
TCP connection, or use multiple TCP connections to carry one
logical connection, or both at the same time.

>>Glad it worked, but I'd still disrecommend IDLE...
>
> But it does NOT work without IDLE!

Odd. What happens if you run it from a command line?


> [...] But while I don't understand what's going on


> with the core part of the code this improvement doesn't much
> matter.

Do you want to be a network engineer? What's going on is too
many unsafe assumptions, and isolating the one (or ones) biting
you could take a lot of your time. My last version, with the
shutdown fix, is a pretty general TCP spy-proxy. The printing is
a bit dodgy, but other than that, I don't think it assumes
anything that TCP doesn't guarantee. (But don't let it walk
alone in crime-ridden neighborhoods such as the Internet.)


--
--Bryan

Message has been deleted

n00m

unread,
Sep 3, 2005, 3:08:49 PM9/3/05
to
Bryan wrote:
> Do you want to be a network engineer?
lol... definetely not! It's just my curiosity.
At my work my tools are: vba, vbs, jet-sql (ms access),
t-sql (ms sql server). The pretty humble set.

> My first two guess are:

> The client is trying to make more than one connection.

> Putting accept in a loop and moving some stuff will support
> that.

BUT your *1st version* does NOT support more than ONE client's
connection! How do I know that? I just ran several (3) instances
of my.vbs (almost) simultaneously and only the first of them could
connect to SQL Server via Python!
Just in case: SQL Server itself can accept up to 32767 clients.

Then (if I'm not wrong here) what's the difference with my own
version? Maybe replacing send() with sendall() will be quite enough
to make it working over LAN? I've NOT tested this!

PS Yes! Your last version works like a champ. It easily handles up
to 5 instances of my.vbs! Except of this thing:
> AttributeError: 'module' object has no attribute 'SHUT_WR'
Seems it's a pure Unix constant.

>> But it does NOT work without IDLE!

> Odd. What happens if you run it from a command line?

In a moment - AFTER I start my.vbs - in console window new prompt
"D:\>" appears... and vbs reports "General Network Error".

Dennis;
No no no! It's NOT firewalls trick. It's NOT db permissions issue.
VBS and SQL Server work with each other ABSOLUTELY FINE - from ANY
machine at ANY time at ANY free port - BUT WITHOUT Python being a
mediator for them.

Bryan Olson

unread,
Sep 3, 2005, 4:20:31 PM9/3/05
to
n00m wrote:
> Your last version works like a champ. It easily handles up
> to 5 instances of my.vbs! Except of this thing:
>
>>AttributeError: 'module' object has no attribute 'SHUT_WR'
>
> Seems it's a pure Unix constant.

No, my guess is that you're running an old version of Python.
The constant was added in the source on 27 Nov 2003; I'm not
sure what version that would first appear in. You can fix it
either by upgrading your Python distribution (a good idea
anyway), or replacing:

sock.shutdown(socket.SHUT_WR)

with:

sock.shutdown(1)


>>>But it does NOT work without IDLE!
>>
>>Odd. What happens if you run it from a command line?
>
> In a moment - AFTER I start my.vbs - in console window new prompt
> "D:\>" appears... and vbs reports "General Network Error".

Hmmm... not much to go on there. I tested it on Win-XP, running
it from a command line. I set the server to ('www.googl.com',
80), and I was able to web-search through it.

Are you running XP's local firewall?


--
--Bryan

Peter Hansen

unread,
Sep 3, 2005, 4:42:35 PM9/3/05
to
n00m wrote:

> Bryan wrote:
> PS Yes! Your last version works like a champ. It easily handles up
> to 5 instances of my.vbs! Except of this thing:
>
>>AttributeError: 'module' object has no attribute 'SHUT_WR'
>
> Seems it's a pure Unix constant.

Definitely not. Are you sure you've got a proper Python install?

c:\>python
Python 2.4.1 (#65, Mar 30 2005, 09:13:57) [MSC v.1310 32 bit (Intel)] on
win32
>>> import socket
>>> dir(socket)
['AF_APPLETALK', 'AF_DECnet', ... 'SHUT_RD', 'SHUT_RDWR', 'SHUT_WR',
'SOCK_DGRAM', ... 'sys', 'timeout']

>>> socket.SHUT_WR
1

If you're really getting this error it would seem something is very
wrong on your machine.

-Peter

Message has been deleted

n00m

unread,
Sep 3, 2005, 5:35:30 PM9/3/05
to
1.
Python 2.3.4

2.
Win98 and Win2k Professional

Message has been deleted

Bryan Olson

unread,
Sep 3, 2005, 6:35:51 PM9/3/05
to
Dennis Lee Bieber wrote:
> Bryan Olson declaimed the following in comp.lang.python:

>
>>No, my guess is that you're running an old version of Python.
>>The constant was added in the source on 27 Nov 2003; I'm not
>
>
> Are you sure of that 2003?

Yes, but that's when it went into the source, in the sense of
first being edited into a file. It was Revision 1.279 of
socketmodule.c.

http://cvs.sourceforge.net/viewcvs.py/python/python/dist/src/Modules/socketmodule.c?rev=1.312&view=log


--
--Bryan

n00m

unread,
Sep 3, 2005, 7:43:06 PM9/3/05
to
Bryan;
Look at how I corrected your the very first version
(see added arguments in both functions). And now it
really can handle multiple connections!


import socket, thread

sqls_host, sqls_port = '127.0.0.1', 1433
proxy_host, proxy_port = '127.0.0.1', 1434

# How I tested it:
# sqls_host, sqls_port = 'www.google.com', 80

def VB_SCRIPT(s2, cn):


while 1:
data = cn.recv(4096)
if not data: return

s2.sendall(data)
print 'VB_SCRIPT:' + data + '\n'

def SQL_SERVER(s2, cn):


while 1:
data = s2.recv(4096)
if not data: return

cn.sendall(data)
print 'SQL_SERVER:' + data + '\n'

s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind((proxy_host, proxy_port))
s1.listen(5)

while 1:
cn, addr = s1.accept()


s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.connect((sqls_host, sqls_port))

thread.start_new_thread(VB_SCRIPT,(s2, cn))
thread.start_new_thread(SQL_SERVER,(s2, cn))


Without these corrections I got these error messages
when I launched SIMULTANEOUSLY 3 instances of my.vbs:


Unhandled exception in thread started by
Unhandled exception in thread started by
Traceback (most recent call last):
Traceback (most recent call last):
File "D:\Python23\00\socket_Br10.py", line 18, in SQL_SERVER
File "D:\Python23\00\socket_Br10.py", line 13, in VB_SCRIPT
data = s2.recv(4096)
s2.sendall(data)
socket File "<string>", line 1, in sendall
.socketerror.: error: (10054, 'Connection reset by peer')
(10054, 'Connection reset by peer')

Bryan Olson

unread,
Sep 4, 2005, 3:48:43 AM9/4/05
to
n00m wrote:
> Bryan;
> Look at how I corrected your the very first version
> (see added arguments in both functions). And now it
> really can handle multiple connections!

Ah, yes, I see. (In my defense, I had already fixed that bug in
my second version.)


--
--Bryan

n00m

unread,
Sep 4, 2005, 9:41:53 AM9/4/05
to
Bryan Olson wrote:
> Ah, yes, I see. (In my defense, I had already fixed that bug in
> my second version.)
1.
Yes! I myself noticed that, but your 2nd version looks
a bit more verbose.
2.
This all means... what? ONLY send() vs sendall() matters?
Sometimes send() really sends ALL and my version works too!
I must give it a thorough testing!
3.
See how it looks in SQL Server Profiler (it's its utility for
tracing client/server events) WHEN I started 5 copies of .vbs.
http://free.7host02.com/n00b/SQL_Profiler.gif

Btw, without s2.shutdown(1) those vbs' do NOT disconnect from
the server (see DISCONNECT events on the gif).


The latest python version:
==============================
import socket, thread

sqls_host, sqls_port = '127.0.0.1', 1433
proxy_host, proxy_port = '127.0.0.1', 1434

# How I tested it:
# sqls_host, sqls_port = 'www.google.com', 80

def VB_SCRIPT(s2, cn):
while 1:
data = cn.recv(4096)
if not data:

s2.shutdown(1)


return
s2.sendall(data)
print 'VB_SCRIPT:' + data + '\n'

def SQL_SERVER(s2, cn):
while 1:
data = s2.recv(4096)
if not data: return
cn.sendall(data)
print 'SQL_SERVER:' + data + '\n'

s1 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s1.bind((proxy_host, proxy_port))
s1.listen(5)

while 1:
cn, addr = s1.accept()
s2 = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s2.connect((sqls_host, sqls_port))
thread.start_new_thread(VB_SCRIPT,(s2, cn))
thread.start_new_thread(SQL_SERVER,(s2, cn))


The vbs text:
==============


Set cn = CreateObject("ADODB.Connection")

cn.Open _
"Provider=sqloledb;Data Source=127.0.0.1,1434;" & _
"Network Library=DBMSSOCN;Initial Catalog=pubs;" & _
"User ID=qwe;Password=asdasd;"
cn.Execute _
"select 'AAAAAAAAAAAAAAA';" & _
"waitfor delay '00:00:02'; raiserror('XXX',10,1) with nowait;" & _
"waitfor delay '00:00:02'; raiserror('YYY',10,1) with nowait;" & _
"waitfor delay '00:00:02'; raiserror('ZZZ',10,1) with nowait;" & _
"select 'BBBBBBBBBBBBBBB';"
cn.Close
Set cn = Nothing

Phill Atwood

unread,
Sep 6, 2005, 10:36:58 PM9/6/05
to

Newbie question:

I have a dictionary called "rec". And a list called "db". db is my
database. rec are to be records in the database. In a loop I'm trying to
create a record and add it to my database. The key stmt is

db.append( rec )

This works initially but it seems that instead of copying the values in
rec and adding it to db, only a reference of rec is added to db. Thus
when I reassign rec with new data and then do another append I end up
with two records in my database but now the both contain the same data,
namely the latest version or rec.

So how do I add a dictionary into a list by value rather than by reference?

The complete code is here:

=========================================================
#!/usr/bin/python

import sys

inputfile = sys.argv[1]

keywords = [ 'place-name=',
'addr-line1=',
'addr-line2=',
'addr-city=',
'addr-state=',
'addr-country=',
'addr-postalcode=',
'mailaddr-line1=',
'mailaddr-line2=',
'mailaddr-city=',
'mailaddr-state=',
'mailaddr-country=',
'mailaddr-postalcode=',
'place-phone1=',
'place-phone2=',
'place-fax=',
'place-email1=',
'place-email2=' ]

def csv_it():
db = [] # the entire database of records
rec = {} # a single rec: a dictionary of field names and data pairs
fields = [] # list of field names collected so far for current record
for line in open(inputfile):
kword = getkeyword(line) # get keyword (or field name)
if kword:
# We've got a line with a keyword in it
if kword == keywords[0]:
# Starting a new record, so save current record
db.append( rec )
printdb(db, "stage 1")

# Now clear current record
fields = []
rec.clear()
dummylist = []
for i in range(1,len(keywords)+1):
dummylist.append('')
for k,d in zip(keywords,dummylist):
rec[k] = d
printdb(db, "stage 2")

# make sure we are not encountering a duplicate key word
if kword in fields:
print "Record contains duplicate field"
print line,
sys.exit()
fields.append(kword)
# collect our data and store it in the current record
data = line[line.find('=')+1:]
datalstrip = data.lstrip()
datarstrip = datalstrip.rstrip()
rec[kword] = datarstrip

printdb(db,"stage 3")
db.append( rec ) # don't forget whatever we have in our last record

# dump the database in comma separated value form
outstring = ''
for k in keywords:
outstring += '"'
outstring += k
outstring += '"'
outstring += ','
print outstring
for r in db:
outstring = ''
for k in keywords:
if r[k]:
outstring += '"'
outstring += r[k]
outstring += '"'
outstring += ','
print outstring


def getkeyword(line):
equal_index = line.find('=')
if equal_index >= 0:
kword = line[0:equal_index+1]
if kword in keywords:
return kword
else:
print "Invalid keyword at line:"
print line
sys.exit()
return None

def printdb( db, text ):
print " "
print "db %s = " % text
print db
print " "

if __name__ == '__main__':
csv_it()

====================================================

Thanks
Phill

Steve Holden

unread,
Sep 6, 2005, 11:40:20 PM9/6/05
to pytho...@python.org
Phill Atwood wrote:
> Newbie question:
>
> I have a dictionary called "rec". And a list called "db". db is my
> database. rec are to be records in the database. In a loop I'm trying to
> create a record and add it to my database. The key stmt is
>
> db.append( rec )
>
> This works initially but it seems that instead of copying the values in
> rec and adding it to db, only a reference of rec is added to db. Thus
> when I reassign rec with new data and then do another append I end up
> with two records in my database but now the both contain the same data,
> namely the latest version or rec.
>
> So how do I add a dictionary into a list by value rather than by reference?
>
> The complete code is here:
>
[code snipped]

I see you do a rec.clear() to clear out the contents of one record
before creating a new one. Python only *ever* uses references, so why
not just use

rec = {}

instead of rec.clear()?

regards
Steve
--
Steve Holden +44 150 684 7255 +1 800 494 3119
Holden Web LLC http://www.holdenweb.com/

Terry Reedy

unread,
Sep 7, 2005, 1:43:18 AM9/7/05
to pytho...@python.org

"Phill Atwood" <fakea...@nowhere.org> wrote in message
news:WosTe.9302$vN.4...@news20.bellglobal.com...

> def csv_it():
> db = [] # the entire database of records
> rec = {} # a single rec: a dictionary of field names and data pairs

Move this line

> fields = [] # list of field names collected so far for current record
> for line in open(inputfile):

to here

> kword = getkeyword(line) # get keyword (or field name)

...


> # Now clear current record
> fields = []
> rec.clear()

and delete this

> dummylist = []

and I think you will have what you want (or close).
The initial fields = [] line could be moved also, I believe, without
thoroughly reading your code.

Terry J. Reedy

Bryan Olson

unread,
Sep 7, 2005, 4:26:41 AM9/7/05
to

Phill Atwood wrote:
[...]

> So how do I add a dictionary into a list by value rather than
> by reference?

Is rec.items() what you want? It returns a list of (key, value)
tuples.


> The complete code is here:

[...]

Looks like you could use Python's ConfigParser module.

http://docs.python.org/lib/module-ConfigParser.html


--
--Bryan

n00m

unread,
Sep 7, 2005, 1:07:41 PM9/7/05
to
I was trying to test the send() vs sendall() like this:

x=send(data)
print len(data)-x > 0 ? (when the code fails)

but I could not reproduce the failures anymore.
As if the lan got "refreshed" after the first
using of sendall() instead of send().

Btw, why we need send() if there is sendall()?

Bryan Olson

unread,
Sep 7, 2005, 3:13:34 PM9/7/05
to
n00m wrote:
> Btw, why we need send() if there is sendall()?

Mostly because sendall() can block, even if you do all the
select() and setblocking() magic. That's no problem in the
threaded architecture we're using, but a deal-breaker for a
single-threaded server.

--
--Bryan

n00m

unread,
Sep 8, 2005, 5:58:36 AM9/8/05
to
Thanks, Bryan, for the details!

Btw, the newest oops in the topic's subject is:
the code does not work in the case of:

sqls_host, sqls_port = '192.168.0.8', 1433
proxy_host, proxy_port = '192.168.0.3', 1434
## proxy_host, proxy_port = '127.0.0.1', 1434
## proxy_host, proxy_port = '', 1434

I.e. when both Python and vbs script run on one machine
(with ip = 192.168.0.3) and SQL Server runs on another
(with ip = 192.168.0.8)

How namely it does not work:
in the idle window only one line is printed:

VB_SCRIPT: .........

that's all. No errors from Python. After timeout expires
I get an error message from VBS (smth like preHandShake()
failed; I've never seen it before).

I just wonder MUST (or not) it work at all (IN THEORY)?

PS: again, without Python vbs and sql server contact with
each other PERFECTLY.

Bryan Olson

unread,
Sep 9, 2005, 5:27:26 AM9/9/05
to
n00m wrote:
[...]

> Btw, the newest oops in the topic's subject is:
> the code does not work in the case of:
>
> sqls_host, sqls_port = '192.168.0.8', 1433
> proxy_host, proxy_port = '192.168.0.3', 1434
> ## proxy_host, proxy_port = '127.0.0.1', 1434
> ## proxy_host, proxy_port = '', 1434
>
> I.e. when both Python and vbs script run on one machine
> (with ip = 192.168.0.3) and SQL Server runs on another
> (with ip = 192.168.0.8)
>
> How namely it does not work:
> in the idle window only one line is printed:
>
> VB_SCRIPT: .........
>
> that's all. No errors from Python. After timeout expires
> I get an error message from VBS (smth like preHandShake()
> failed; I've never seen it before).
>
> I just wonder MUST (or not) it work at all (IN THEORY)?

No theoretically-must-or-even-should-work solution is generally
possible. Protocols can thwart proxies by using addresses that
they transfer within their payload-data. That's an essential
feature of some security protocols, such as SSL, and an
unfortunate consequence of some old or badly-designed protocols.

Were I a betting man (outside of Texas Hold'em, where I am), I'd
wager that your problem is more basic. The code you're running,
the settings you're setting, or -- well -- something there, is
not right.


--
--Bryan

0 new messages