1

I am kind of new to python. I am currently trying to make and use a list/array of sockets in a program. So I have declared an array as follows:

myCSocks = ['CSock1', 'CSock2', 'CSock3', 'CSock4', 'CSock5']

And I am trying to use my array elements as follows:

myCSocks[i], addr = serverSocket.accept()
message = myCSocks[i].recv(1024)

I am getting the following error:

Traceback (most recent call last):
  File "./htmlserv_multi.py", line 22, in <module>
    message = myCSocks[i].recv(1024)
AttributeError: 'str' object has no attribute 'recv'

This kind of makes sense to me, it is saying that my array elements are of type String and are not sockets. So I understand what my problem is but I do not know how to remedy it. I have googled "list of sockets python" but did not find anything. Any help will be greatly appreciated. Thank you.

PS: My final objective is to create a very simple multithreaded TCP web server (using python)

CODE:

#! /usr/bin/env python
from socket import *

#does this work?
myCSocks = []

serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('192.168.1.4',12000))
serverSocket.listen(5)
while True:
  for i in range(0, len(myCSocks)+1):
    myCSocks[i], addr = serverSocket.accept()
  try:
    for i in range(0, len(myCSocks)):
      message = myCSocks[i].recv(1024)
      filename = message.split()[1]
      f = open(filename[1:])
      outputdata = f.read()
      myCSocks[i].send('HTTP/1.1 200 OK\r\n\r\n')
      for p in range(0, len(outputdata)):
        myCSocks[i].send(outputdata[p])
      myCSocks[i].close()
  except IOError:
    connectionSocket.send('HTTP/1.1 404 Bad Request\r\n\r\n')
    connectionSocket.send('<HTML><p>ERROR 404: BAD REQUEST!</p></HTML>')
    serverSocket.close()
    exit()
Perplexabot
  • 1,852
  • 3
  • 19
  • 22

3 Answers3

2

Have a look at the built-in socket module here (http://docs.python.org/2/library/socket.html). This allows you to create sockets, and send and receive data, and there are simple examples in the online documentation. Your code will probably work if you replace the strings with actual sockets. If you want to store several sockets by name, you could use a dictionary:

theDict = {}
theDict['socket1'] = socket.socket()

etc.

Andy Rimmer
  • 1,901
  • 1
  • 13
  • 9
  • I am getting a new error. If I were using C/C++ I would initialize an array in the heap and create a new socket everytime a connection was established. I do no know how to do that with python. Any suggestions? – Perplexabot Oct 26 '13 at 22:38
  • What is the error? It would help if you posted your code and any relevant output. – Andy Rimmer Oct 26 '13 at 22:42
  • Hey, i edited my OP and included the code. I know this will not work due to the fact that my array is initialized to be empty. I am trying to figure out what to do. Thank you. – Perplexabot Oct 26 '13 at 23:01
1

If CSock1 is a class already defined you can just refer to the class objects. However, if you are trying to do a multi-threaded, there's better ways to do that: Multithreaded web server in python. If you are just trying to use sockets, I'd look at Multi Threaded TCP server in Python (the second answer is best).

Community
  • 1
  • 1
Peter Halliday
  • 301
  • 1
  • 6
  • Is it possible to implement a multithreaded web server with only the "socket" library? I don't need a robust server, I just want to demonstrate how multithreading works. Thank you for your initial reply. – Perplexabot Oct 26 '13 at 22:18
  • Just read your edit. The new link you referred me to looks fairly simple, however it uses the threading library which I have no clue how to use. I will research threading library now and see what happens. Thank you – Perplexabot Oct 26 '13 at 23:01
1

A very simple echo TCP (SOCK_STREAM) server demonstrating how to implement a multiprocessing server. Makes use of threadPoolExecutor to accept connections asynchronously.

Server:

import socket
import concurrent.futures


def server_instance(addr):
    HOST = addr[0]
    PORT = addr[1]
    with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
        s.bind((HOST, PORT))
        s.listen()
        conn, addr = s.accept()
        with conn:
            print(f"Linked with: {addr}")
            while True:
                data = conn.recv(1024)
                if not data:
                    break
                conn.sendall(data)
    return f'DONE'


addresses = [
    ('127.0.0.1', 65432),
    ('127.0.0.1', 65431),
    ('127.0.0.1', 65433),
    ('127.0.0.1', 65435),
    ('127.0.0.1', 65434),
]


with concurrent.futures.ThreadPoolExecutor() as executor:
    for address, status in zip(addresses, executor.map(server_instance, addresses)):
        print(f"{address}: {status}")

A client to send data to server.

Client:

import socket
import sys

HOST = '127.0.0.1'


if len(sys.argv) != 3:
    print(f"[*] Usage: python {sys.argv[0]} <PORT> <MESSAGE>")
    sys.exit()

PORT = int(sys.argv[1])
print(f"PORT SET TO: {PORT}")

MSG = bytes(sys.argv[2], encoding='utf8')
print(f"MESSAGE SET TO: {MSG}")

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(MSG)
    data = s.recv(1024)

print(f'[r] {repr(data)}')

f-strings require python3.6 and up

concurrent futures require python 3.2 and up

Perplexabot
  • 1,852
  • 3
  • 19
  • 22