1. 程式人生 > >面向連接的tcp 編程

面向連接的tcp 編程

print customer 屬性 設置 建立連接 epo reading bre sleep

from socket import *
serverSocket=socket(AF_INET,SOCK_STREAM)
serverSocket.bind(("",8899))
serverSocket.listen(5)
newSocket,clientAddr=serverSocket.accept()     #返回新的套接字和對方的ip地址和端口號
print("有客戶端連接")
recvDate=newSocket.revc(1024)
print("%s%s"%(str(clientAddr),recvDate))
newSocket.send("
thank you !") newSocket.close() serverSocket.close()

from socket import *

# 創建socket
tcpSerSocket = socket(AF_INET, SOCK_STREAM)

# 綁定本地信息
address = (‘‘, 8899)
tcpSerSocket.bind(address)

# 使用socket創建的套接字默認的屬性是主動的,使用listen將其變為被動的,這樣就可以接收別人的鏈接了
tcpSerSocket.listen(5)

# 如果有新的客戶端來鏈接服務器,那麽就產生一個新的套接字專門為這個客戶端服務器
# newSocket用來為這個客戶端服務 # tcpSerSocket就可以省下來專門等待其他新客戶端的鏈接 newSocket, clientAddr = tcpSerSocket.accept() # 接收對方發送過來的數據,最大接收1024個字節 recvData = newSocket.recv(1024) print(接收到的數據為:%d,recvData.decode("gb2312")) # 發送一些數據到客戶端 newSocket.send("thank you !".encode("gb2312")) # 關閉為這個客戶端服務的套接字,只要關閉了,就意味著為不能再為這個客戶端服務了,如果還需要服務,只能再次重新連接
newSocket.close() # 關閉監聽套接字,只要這個套接字關閉了,就意味著整個程序不能再接收任何新的客戶端的連接 tcpSerSocket.close()

# 多線程服務器,接收客戶機鏈接

from socket import *
from threading import *


def recv_send_Thread(customer_sock,addr):
    while True:

        str=customer_sock.recv(1024)                                  # 循環接收客戶端發來的信息
        customer_sock.send(str)
        print(str.decode("gb2312"))
        if str.decode("gb2312") == exit:
            print("關閉套接字")
            customer_sock.close()
            break
    customer_sock.close()
#創建服務器的socket
server_tcp_socket=socket(AF_INET,SOCK_STREAM)

# 解決MSL問題,如果服務器先斷開鏈接,則第四次會後不必等2被時間,即可鏈接,避免出現等到2倍時間內地址被占用的問題
server_tcp_socket.setsockopt(SOL_SOCKET,SO_REUSEADDR,1)


#bind綁定地址和端口
server_tcp_socket.bind(("",8899))

#設置監聽listen
server_tcp_socket.listen(5)

while True:
    new_socket,new_addr=server_tcp_socket.accept()       #等待接受客戶端鏈接
    print(("與客戶%s建立鏈接成功,可以交流" % new_addr[0]))
    new_socket.send(("您好客戶%s,已經建立鏈接,可以交流" % new_addr[0]).encode("gb2312"))           #  鏈接成功後,發送鏈接信息
    th=Thread(target=recv_send_Thread,args=(new_socket,new_addr))
    th.start()
    th.join()


#收發信息


#釋放鏈接
server_tcp_socket.close()

#select版本的服務器代碼
#輪詢的方式檢測,效率低;32位最多鏈接1023個,64位最多鏈接2045個端口
from socket import *
from select import select
from sys import *

def main():

    server = socket(AF_INET,SOCK_STREAM)
    # 解決MSL問題,如果服務器先斷開鏈接,則第四次會後不必等2被時間,即可鏈接,避免出現等到2倍時間內地址被占用的問題
    server.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    address = ("",8000)
    server.bind(address)
    server.listen(1024)
    inputs=[server,stdin]
    running = True
    while True:
        readable,writeable,exceptional = select(inputs,[],[])
        for sock in readable:

            if(sock == server):
                s,addr = server.accept()
                print(s)
                inputs.append(s)
                s.send("已經建立好鏈接".encode("gb2312"))
            elif sock == stdin:
                cmd = stdin.readline()
                running = False
                break
            else:
                msg = sock.recv(1024)
                print(msg.decode("gb2312"))
                sock.send(("服務器收到了客戶端發送的:%s"%(msg.decode("gb2312"))).encode("gb2312"))
                if msg.decode("gb2312")==exit:
                    #sock.send("將要斷開鏈接".encode("gb2312"))
                    sock.close()
                    inputs.remove(sock)
        if running==False:
            break
    server.close()
    print("服務器關閉")
if __name__ =="__main__":
    main()

# epool 方式實現服務器
# epool是沒有套接字上限,是時間通知機制。     pool是輪詢機制,解決了套接字有上限的問題。

from socket import *
from select import *

s = socket(AF_INET,SOCK_STREAM)
# 解決MSL問題,如果服務器先斷開鏈接,則第四次會後不必等2被時間,即可鏈接,避免出現等到2倍時間內地址被占用的問題
s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
addr=("",8000)
s.bind(addr)
s.listen(10)
epoll_l = epoll()
epoll_l.register(s.fileno(),EPOLLIN|EPOLLET)

connections={}
addresses={}

while True:
    epoll_list = epoll_l.poll()

    for fd,events in epoll_list:
        if fd == s.fileno():
            soc,addres = s.accept()
            soc.send("已經鏈接鏈接".encode("gb2312"))
            connections[soc.fileno()] = soc
            addresses[soc.fileno()] = addres

            epoll_l.register(soc.fileno(), EPOLLIN|EPOLLET)
        elif events == EPOLLIN:

            msg = connections[fd].recv(1024)
            print(msg.decode("gb2312"))
            connections[fd].send(("收到了客戶端的%s"%msg.decode("gb2312")).encode("gb2312"))
            if msg.decode("gb2312") == "exit":
                epoll_l.unregister(fd)
                connections[fd].close()
                print()
        else:
            pass

# 協程,生成器版本

import time

def A():
    while True:
        print("----a----")
        yield
        time.sleep(1)

def B(c):
    while True:
        print("----b----")
        c.__next__()
        time.sleep(1)

a=A()
print(a.__next__())
b=B(a)

# 協程,greenlet版本

from greenlet import greenlet
import time

def test1():
    while True:
        print("A")
        gr2.switch()
        time.sleep(1)

def test2():
    while True:
        print("B")
        gr1.switch()
        time.sleep(1)

gr1=greenlet(test1)
gr2=greenlet(test2)

gr1.switch()

#  gevent版本的服務器

import gevent
#from socket import *
from gevent import socket,monkey
monkey.patch_all()

def handle_request(conn):
    while True:
        data=conn.recv(1024)
        if not data:
            conn.close()
            break
        print("recv:%s"%data.decode("gb2312"))
        conn.send(data)

def server(port):
    s=socket.socket()
    # 解決MSL問題,如果服務器先斷開鏈接,則第四次會後不必等2被時間,即可鏈接,避免出現等到2倍時間內地址被占用的問題
    #s.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1)
    s.bind(("",port))
    s.listen(5)
    while True:
        cli,addr = s.accept()
        cli.send("已經連接成功".encode("gb2312"))
        gevent.spawn(handle_request,cli)

if __name__=="__main__":
    server(8000)

客戶端程序:

# 客戶端程序
from socket import *

# 創建socket
tcpClientSocket = socket(AF_INET, SOCK_STREAM)

# 鏈接服務器
serAddr = (192.168.249.210, 8000)
tcpClientSocket.connect(serAddr)                                          # 建立連接
recvData = tcpClientSocket.recv(1024)                                     # 接收數據
print(接收到的數據為:+recvData.decode("gb2312"))
while True:
    # 提示用戶輸入數據
    sendData = input("請輸入要發送的數據:")
    tcpClientSocket.send(sendData.encode("gb2312"))                      # 循環發送數據
    if sendData == "exit":
        break
        # 接收對方發送過來的數據,最大接收1024個字節
    recvData = tcpClientSocket.recv(1024)                                # 循環接收數據
    print(接收到的數據為:+recvData.decode("gb2312"))

# 關閉套接字
tcpClientSocket.close()

面向連接的tcp 編程