python的socket通信实例

一、socket简介

1. 套接字

套接字是为特定网络协议(例如TCP/IP,ICMP/IP,UDP/IP等)套件对上的网络应用程序提供者提供当前可移植标准的对象。

它们允许程序接受并进行连接,如发送和接受数据。为了建立通信通道,网络通信的每个端点拥有一个套接字对象极为重要。

套接字为BSD UNIX系统核心的一部分,而且他们也被许多其他类似UNIX的操作系统包括Linux所采纳。

许多非BSD UNIX系统(如ms-dos,windows,os/2,mac os及大部分主机环境)都以库形式提供对套接字的支持。

三种最流行的套接字类型是:stream,datagram和raw。

stream和datagram套接字可以直接与TCP协议进行接口,

raw套接字则接口到IP协议。

但套接字并不限于TCP/IP。

2、套接字模块

套接字模块是一个非常简单的基于对象的接口,它提供对低层BSD套接字样式网络的访问。

使用该模块可以实现客户机和服务器套接字。

要在python 中建立具有TCP和流套接字的简单服务器,需要使用socket模块。

利用该模块包含的函数和类定义,可生成通过网络通信的程序。

3. 一般来说,建立服务器连接需要六个步骤。

第1步: 创建socket对象。

调用socket构造函数。

socket=socket.socket(familly,type)

family的值可以是AF_UNIX(Unix域,用于同一台机器上的进程间通讯),也可以是AF_INET(对于IPV4协议的TCP和 UDP),

至于type参数,SOCK_STREAM(流套接字)或者 SOCK_DGRAM(数据报文套接字),SOCK_RAW(raw套接字)。

第2步: 是将socket绑定(指派)到指定地址上,socket.bind(address)

address必须是一个双元素元组,((host,port)),主机名或者ip地址+端口号。

如果端口号正在被使用或者保留,或者主机名或ip地址错误,则引发socke.error异常。

第3步: 绑定后,必须准备好套接字,以便接受连接请求。

socket.listen(backlog)

backlog指定了最多连接数,至少为1,接到连接请求后,这些请求必须排队,如果队列已满,则拒绝请求。

第4步: 服务器套接字通过socket的accept方法等待客户请求一个连接:

connection,address=socket.accept()

调用accept方法时,socket会进入‘waiting‘(或阻塞)状态。客户请求连接时,方法建立连接并返回服务器。

accept方法返回一个含有俩个元素的元组,形如(connection,address)。

第一个元素(connection)是新的socket对象,服务器通过它与客户通信;

第二个元素(address)是客户的internet地址。

第5步: 处理阶段,

服务器和客户通过send和recv方法通信(传输数据)。

服务器调用send,并采用字符串形式向客户发送信息。send方法返回已发送的字符个数。

服务器使用recv方法从客户接受信息。调用recv时,必须指定一个整数来控制本次调用所接受的最大数据量。

recv方法在接受数据时会进入‘blocket‘状态,最后返回一个字符串,用它来表示收到的数据。

如果发送的量超过recv所允许,数据会被截断。

多余的数据将缓冲于接受端。以后调用recv时,多余的数据会从缓冲区删除。

第6步: 传输结束,

服务器调用socket的close方法以关闭连接。

4. 建立一个简单客户连接则需要4个步骤。

第1步,创建一个socket以连接服务器 socket=socket.socket(family,type)

第2步,使用socket的connect方法连接服务器 socket.connect((host,port))

第3步,客户和服务器通过send和recv方法通信。

第4步,结束后,客户通过调用socket的close方法来关闭连接。

5. python 编写server的步骤:

第一步是创建socket对象。调用socket构造函数。如:

socket = socket.socket( family, type )

family参数代表地址家族,可为AF_INET或AF_UNIX。

AF_INET家族包括Internet地址,AF_UNIX家族用于同一台机器上的进程间通信。

type参数代表套接字类型,可为SOCK_STREAM(流套接字)和SOCK_DGRAM(数据报套接字)。

第二步是将socket绑定到指定地址。这是通过socket对象的bind方法来实现的:

socket.bind( address )

由AF_INET所创建的套接字,address地址必须是一个双元素元组,格式是(host,port)。

host代表主机,port代表端口号。

如果端口号正在使用、主机名不正确或端口已被保留,bind方法将引发socket.error异常。

第三步是使用socket套接字的listen方法接收连接请求。

socket.listen( backlog )

backlog指定最多允许多少个客户连接到服务器。它的值至少为1。

收到连接请求后,这些请求需要排队,如果队列满,就拒绝请求。

第四步是服务器套接字通过socket的accept方法等待客户请求一个连接。

connection, address = socket.accept()

调 用accept方法时,socket会时入“waiting”状态。客户请求连接时,方法建立连接并返回服务器。

accept方法返回一个含有两个元素的 元组(connection,address)。

第一个元素connection是新的socket对象,服务器必须通过它与客户通信;

第二个元素 address是客户的Internet地址。

第五步是处理阶段,服务器和客户端通过send和recv方法通信(传输 数据)。

服务器调用send,并采用字符串形式向客户发送信息。send方法返回已发送的字符个数。服务器使用recv方法从客户接收信息。

调用recv 时,服务器必须指定一个整数,它对应于可通过本次方法调用来接收的最大数据量。

recv方法在接收数据时会进入“blocked”状态,最后返回一个字符 串,用它表示收到的数据。

如果发送的数据量超过了recv所允许的,数据会被截短。多余的数据将缓冲于接收端。

以后调用recv时,多余的数据会从缓冲区 删除(以及自上次调用recv以来,客户可能发送的其它任何数据)。

传输结束,服务器调用socket的close方法关闭连接。

6.python编写client的步骤:

创建一个socket以连接服务器:

socket = socket.socket( family, type )

使用socket的connect方法连接服务器。对于AF_INET家族,连接格式如下:

socket.connect( (host,port) )

host代表服务器主机名或IP,port代表服务器进程所绑定的端口号。

如连接成功,客户就可通过套接字与服务器通信,如果连接失败,会引发socket.error异常。

处理阶段,客户和服务器将通过send方法和recv方法通信。

传输结束,客户通过调用socket的close方法关闭连接。

二、socket通信的简单的例子

1. TCP server端代码

#!/usr/bin/env python

#

# -*- coding:utf-8 -*-

#

from socket import *

from time import ctime

HOST = ‘‘

PORT = 21567

BUFSIZE=1024

ADDR=(HOST, PORT)

tcpSrvSock=socket(AF_INET, SOCK_STREAM)

tcpSrvSock.bind(ADDR)

tcpSrvSock.listen(5)

while True:

print ‘waiting for connection ...‘

tcpCliSock,addr = tcpSrvSock.accept()

print ‘... connected from:‘, addr

while True:

data=tcpCliSock.recv(BUFSIZE)

if not data:

break

tcpCliSock.send(‘[%s] %s‘%(ctime(), data))

print [ctime()],‘:‘,data

tcpCliSock.close()

tcpSrvSock.close()

2. TCP client端代码

#!/usr/bin/env python

#

# -*- coding:utf-8 -*-

#

from socket import *

HOST=‘localhost‘

PORT=21567

BUFSIZE=1024

ADDR=(HOST, PORT)

tcpCliSock=socket(AF_INET, SOCK_STREAM)

tcpCliSock.connect(ADDR)

while True:

data = raw_input(‘>‘)

if not data:

break

tcpCliSock.send(data)

data=tcpCliSock.recv(BUFSIZE)

if not data:

break

print data

tcpCliSock.close()

三、使用SocketServer模块实现TCP和UDP通信

SocketServer模块简化了网络服务器的开发。

它提供了四个基本的服务器类:

TCPServer : 用于TCP协议,它提供客户端与服务端之间连续的数据流通信;

UDPServer : 用于UDP协议,它的数据封装包是无序的,且有可能会在传输中丢失;

UnixStreamServer和UnixDatagramServer: 它们不经常用;

这四个类处理同步请求,即只有当当前请求处理完成后,才能开始处理下一个请求。

如果每个请求的处理需要很长时间才能完成,这种方式就不是很适合。

因为它要求大量的计算,或因为它返回了大量的数据导致客户端处理很慢。

解决办法是创建一个独立的进程或线程来处理每个请求,

使用 ForkingMixIn和ThreadingMixIn mix-in类能实现异步方式;

创建一个服务器有以下几个步骤,

首先,创建一个BaseRequestHandler类的子类,并重写handle()方法,这个方法将处理输入的请求。

然后,必须实例一个服务器类,并定义它的服务器地址和请求处理类;

最后,调用这个服务器对象的request()或 serve_forever() 方法来处理一个或多个请求。

当继承了ThreadingMixIn来线程化处理连接行为时,需要明确定义你的线程在遇到异常关闭的处理行为。

ThreadingMixIn类定义了一个属性 daemon_threads, 它用来指示服务器是否要等线程线束。

如果你希望线程行为自动处理,你需要显示设置这个标志。

它的默认值是 False,意思是在由ThreadingMinIn创建的线程未退出前,主线程不会退出。

1. TCP通信

Server端

#!/usr/bin/env python

# -*- coding:utf-8 -*-

#

import SocketServer

class MyTCPHandler(SocketServer.BaseRequestHandler):

"""

The RequestHandler class for our server.

It is instantiated once per connection to the server, and must

override the handle() method to implement communication to the

client.

"""

def handle(self):

# self.request is the TCP socket connected to the client

self.data = self.request.recv(1024).strip()

print "{} wrote:".format(self.client_address[0])

print self.data

# just send back the same data, but upper-cased

self.request.sendall(self.data.upper())

if __name__ == "__main__":

HOST, PORT = "localhost", 21577

# Create the server, binding to localhost on port 21577

SocketServer.TCPServer.allow_reuse_address = True

server = SocketServer.TCPServer((HOST, PORT), MyTCPHandler)

print " .... waiting for connection"

# Activate the server; this will keep running until you

# interrupt the program with Ctrl-C

server.serve_forever()

Client端

#!/usr/bin/env python

# -*- coding:utf-8 -*-

#

from socket import *

HOST = ‘localhost‘

PORT = 21577

BUFSIZE=1024

ADDR = (HOST, PORT)

while True:

tcpCliSock=socket(AF_INET, SOCK_STREAM)

tcpCliSock.connect(ADDR)

data=raw_input(‘>‘)

if not data:

break

tcpCliSock.send(‘%s\r\n‘ % data)

data=tcpCliSock.recv(BUFSIZE)

if not data:

break

print data.strip()

tcpCliSock.close()

运行示例:

Server

$ python TCPServer.py

127.0.0.1 wrote:

hello world with TCP

127.0.0.1 wrote:

python is nice

CLIENT:

$ python TCPClient.py hello world with TCP

Sent:     hello world with TCP

Received: HELLO WORLD WITH TCP

$ python TCPClient.py python is nice

Sent:     python is nice

Received: PYTHON IS NICE

2. UDP通信

SERVER端

import SocketServer

class MyUDPHandler(SocketServer.BaseRequestHandler):

"""

This class works similar to the TCP handler class, except that

self.request consists of a pair of data and client socket, and since

there is no connection the client address must be given explicitly

when sending data back via sendto().

"""

def handle(self):

data = self.request[0].strip()

socket = self.request[1]

print "{} wrote:".format(self.client_address[0])

print data

socket.sendto(data.upper(), self.client_address)

if __name__ == "__main__":

HOST, PORT = "localhost", 9999

server = SocketServer.UDPServer((HOST, PORT), MyUDPHandler)

server.serve_forever()

CLIENT端:

import socket

import sys

HOST, PORT = "localhost", 9999

data = " ".join(sys.argv[1:])

# SOCK_DGRAM is the socket type to use for UDP sockets

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)

# As you can see, there is no connect() call; UDP has no connections.

# Instead, data is directly sent to the recipient via sendto().

sock.sendto(data + "\n", (HOST, PORT))

received = sock.recv(1024)

print "Sent:     {}".format(data)

print "Received: {}".format(received)

四、 使用SocketServer处理多连接

上面的例子一次只能连接一个客户机并出力它的请求,

如果要处理多连接问题,那么有三种主要的方法能实现这个目的:

分叉(forking)、

线程(threading)以及

异步I/O(asynchronous I/O)。

通过对SocketServer服务器使用混入类(mix-in class),派生进程和线程很容易处理。

即使要自己实现它们,这些方法也很容易使用。

它们确实有缺点:

分叉占据资源,并且如果有太多的客户端时分叉不能很好分叉

(尽管如此,对于合理数量的客户端,分叉在现代的UNIX或者Linux系统中是很高效的,如果有一个多CPU系统,那系统效率会更高);

线程处理能导致同步问题。

使用SocketServer框架创建分叉或者线程服务器非常简单:

1. 分叉SocketServer服务器:

#!/usr/bin/env python

from SocketServer import (TCPServer as TCP,

StreamRequestHandler as SRH,

ForkingMixIn as FMI)

from time import ctime

HOST = ‘‘

PORT = 12346

ADDR = (HOST, PORT)

class Server(FMI, TCP):

pass

class MyRequestHandler(SRH):

def handle(self):

print ‘...connected from:‘, self.client_address

self.wfile.write(‘[%s] %s‘ % (ctime(), self.rfile.readline()))

tcpServ = Server(ADDR, MyRequestHandler)

print ‘waiting for connection...‘

tcpServ.serve_forever()

2. 多线程SocketServer服务器:

#!/usr/bin/env python

from SocketServer import (TCPServer as TCP,

StreamRequestHandler as SRH,

ThreadingMixIn as TMI)

from time import ctime

HOST = ‘‘

PORT = 12346

ADDR = (HOST, PORT)

class Server(TMI, TCP):

pass

class MyRequestHandler(SRH):

def handle(self):

print ‘...connected from:‘, self.client_address

self.wfile.write(‘[%s] %s‘ % (ctime(), self.rfile.readline()))

tcpServ = Server(ADDR, MyRequestHandler)

print ‘waiting for connection...‘

tcpServ.serve_forever()

3. 异步的SocketServer服务器

import socket

import threading

import SocketServer

class ThreadedTCPRequestHandler(SocketServer.BaseRequestHandler):

def handle(self):

data = self.request.recv(1024)

cur_thread = threading.current_thread()

response = "{}: {}".format(cur_thread.name, data)

self.request.sendall(response)

class ThreadedTCPServer(SocketServer.ThreadingMixIn, SocketServer.TCPServer):

pass

def client(ip, port, message):

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

sock.connect((ip, port))

try:

sock.sendall(message)

response = sock.recv(1024)

print "Received: {}".format(response)

finally:

sock.close()

if __name__ == "__main__":

# Port 0 means to select an arbitrary unused port

HOST, PORT = "localhost", 0

server = ThreadedTCPServer((HOST, PORT), ThreadedTCPRequestHandler)

ip, port = server.server_address

# Start a thread with the server -- that thread will then start one

# more thread for each request

server_thread = threading.Thread(target=server.serve_forever)

# Exit the server thread when the main thread terminates

server_thread.daemon = True

server_thread.start()

print "Server loop running in thread:", server_thread.name

client(ip, port, "Hello World 1")

client(ip, port, "Hello World 2")

client(ip, port, "Hello World 3")

server.shutdown()

输出示例:

$ python ThreadedTCPServer.py

Server loop running in thread: Thread-1

Received: Thread-2: Hello World 1

Received: Thread-3: Hello World 2

Received: Thread-4: Hello World 3

时间: 2024-10-08 11:13:28

python的socket通信实例的相关文章

java NIO socket 通信实例

java Nio 通信与Bio通信主要不同点: 1.Nio中的单个channel即可支持读操作也可以支持写操作,而bio中读操作要用inputstream,写操作要outputstream. 2.nio 采用byteBuffer 作为内存缓存区,向channel里写或者度操作,bio基本是用byte[] 3.nio采用 selector组件轮询读取就绪channel 服务端demo代码: package com.my.socket3; import java.io.ByteArrayOutput

Java 和 Python 的 Socket 通信

网络上两个程序通过一个双向通讯连接实现数据的交换,这个双向链路的一端称为一个Socket.Socket支持的协议有多种,这里主要介绍基于 TCP/IP 协议族的 Socket 编程. 首先,IP协议族决定了socket的地址类型,在通信中必须采用对应的地址.AF_INET(AF 表示 Adress Family)表示要用 ipv4 地址(32位)与端口号(16位)的组合. 然后,根据传输协议又分为:流式 Socket(SOCK_STREAM) 和数据报式 Socket(SOCK_DGRAM):

(8)Linux(客户端)和Windows(服务端)下socket通信实例

Linux(客户端)和Windows(服务端)下socket通信实例: (1)首先是Windows做客户端,Linux做服务端的程序 Windows   Client端 #include <stdio.h> #include <Windows.h> #pragma comment(lib, "ws2_32.lib") #define Port 5000 #define IP_ADDRESS "192.168.1.30"     //服务器地址

Linux下简单的socket通信实例

Linux下简单的socket通信实例 If you spend too much time thinking about a thing, you’ll never get it done. —Bruce Lee       学习网络编程也一段时间了,刚开始看<UNIX网络编程>的时候,觉得这本厚厚的书好难啊!看到后来,发现并没有想象中的那么难.如果你是新手,建议你看到第二部分结束后,开始着手写代码.不写代码肯定是不行的.看100遍也没有敲一遍实现一遍来的清楚.敲完以后,带着问题去看书,你会

网络协议栈学习(一)socket通信实例

网络协议栈学习(一)socket通信实例 该实例摘自<linux网络编程>(宋敬彬,孙海滨等著). 例子分为服务器端和客户端,客户端连接服务器后从标准输入读取输入的字符串,发送给服务器:服务器接收到字符串后,发送给服务器:服务器接收到字符串后统计字符串的长度,然后将该值传给客户端:客户端将接收到的信息打印到标准输出. 一.服务器端代码 #include <stdio.h> #include <stdlib.h> #include <string.h> #in

Python实现socket通信

介绍 本文介绍如何用python脚本实现socket通信,在一台服务器上开一个端口监听,其他机器通过telnet连进来,模仿B/S模式进行通信. 正文 一共两个文件. webserver.py import socket import re import os PORT = 8080 # Create a Server Socket serversocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) serversocket.bind

python基础-socket通信

socket是一种双向通信的起点和重点,氛围服务器端和客户端 Socket服务器端用到的方法有 Method Description s.bind() This method binds address (hostname, port number pair) to socket. s.listen() This method sets up and start TCP listener. s.accept() This passively accept TCP client connectio

Socket通信实例(C#)

SOCKET原理 一.套接字(socket)概念 套接字(socket)是通信的基石,是支持TCP/IP协议的网络通信的基本操作单元.它是网络通信过程中端点的抽象表示,包含进行网络通信必须的五种信息:连接使用的协议,本地主机的IP地址,本地进程的协议端口,远地主机的IP地址,远地进程的协议端口. 应用层通过传输层进行数据通信时,TCP会遇到同时为多个应用程序进程提供并发服务的问题.多个TCP连接或多个应用程序进程可能需要通过同一个 TCP协议端口传输数据.为了区别不同的应用程序进程和连接,许多计

Linux C++ TCP Socket通信实例

环境:Linux 语言:C++ 通信方式:TCP 下面用TCP协议编写一个简单的服务器.客户端,其中服务器端一直监听本机的6666号端口.如果收到连接请求,将接收请求并接收客户端发来的消息:客户端与服务器端建立连接并发送一条消息. server.cpp 1 #include<stdio.h> 2 #include<stdlib.h> 3 #include<string.h> 4 #include<errno.h> 5 #include<sys/type