Socket

1.Socket概念

Socket,是操作系统内核中的一个数据结构,它是网络中的节点进行相互通信的门户。它是网络进程的ID。网络通信,归根到底还是进程间的通信。在网络中,每一个节点(计算机或路由)都有一个网络地址,也就是IP地址。两个进程通信时,首先要确定各自所在的网络节点的网络地址。但网络地址只能确定进程所在的计算机,这时,socket中还需要包括其他的信息,也就是端口号(PORT),才能确定和哪个进程通信。所以,使用端口号和网络地址的组合可以唯一的确定整个网络中的一个网络进程。

端口号的范围从065535,一类是由互联网指派名字和号码公司ICANN负责分配给一些常用的应用程序固定使用的“周知的端口”,其值一般为01023, 用户自定义端口号一般大于等于1024,

每一个socket都用一个半相关描述{协议、本地地址、本地端口}来表示;一个完整的套接字则用一个相关描述{协议、本地地址、本地端口、远程地址、远程端口}来表示

Socket类型

socket类型在Liunx和Python是一样的, 只是Python中的类型都定义在socket模块中, 调用方式socket.SOCK_XXXX
流式socket(SOCK_STREAM) 用于TCP通信
流式套接字提供可靠的、面向连接的通信流;它使用TCP协议,从而保证了数据传输的正确性和顺序性
数据报socket(SOCK_DGRAM) 用于UDP通信
数据报套接字定义了一种无连接的服务,数据通过相互独立的报文进行传输,是无序的,并且不保证是可靠、无差错的。它使用数据报协议UDP
原始socket(SOCK_RAW) 用于新的网络协议实现的测试等
原始套接字,普通的套接字无法处理ICMP、IGMP等网络报文,而SOCK_RAW可以, 其次,SOCK_RAW也可以处理特殊的IPv4报文;此外,利用原始套接字,可以通过IP_HDRINCL套接字选项由用户构造IP头。

2.Socket编程

TCP通信基本步骤:

socket函数
socket.socket([family[, type[, proto]]])
family : AF_INET (默认ipv4), AF_INET6(ipv6) or AF_UNIX(Unix系统进程间通信).
type : SOCK_STREAM (TCP), SOCK_DGRAM(UDP) .
protocol : 一般为0或者默认

服务器端函数
bind函数
将socket绑定到地址(IP地址+端口号)
s.bind(address)
s为socket.socket()返回的套接字对象
address为元组(host,port)
host: ip地址, 为一个字符串
post: 自定义主机号, 为整型

listen函数
使服务器的这个端口和IP处于监听状态,等待网络中某一客户机的连接请求,如果客户端有连接请求,端口就会接受这个连接,。
s.listen(backlog)
s为socket.socket()返回的套接字对象
backlog : 操作系统可以挂起的最大连接数量。

accept函数
接受远程计算机的连接请求,建立起与客户机之间的通信连接。
s.accept()
s为socket.socket()返回的套接字对象
返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址

客户端函数
connect
用来请求连接远程服务器
s.connect(address)
s为socket.socket()返回的套接字对象
address:格式为元祖(hostname,port)

通用函数
recv
接受远端主机传来的数据
data=s.recv(bufsize[,flag])
s为socket.socket()返回的套接字对象
bufsize:指定要接受的数据大小
flag: 提供有关消息的其他信息,通常可忽略
返回值data以字符串形式

send
发送数据到指定的远端主机
s.send(string[,flag])
s为socket.socket()返回的套接字对象
string : 要发送的字符串数据
flag : 提供有关消息的其他信息,通常可以忽略
返回值是要发送的字节数量,该数量可能小于string的字节大小。
s.sendall(string[,flag])
完整发送TCP数据。将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。
返回值 : 成功返回None,失败则抛出异常。

close
关闭socket
s.close()

客户端服务器TCP连接

#服务器端
import socket   #socket模块
import commands   #执行系统命令模块
 
 
BUF_SIZE = 1024  #设置缓冲区大小
server_addr = ('127.0.0.1', 8888)  #IP和端口构成表示地址
server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #生成一个新的socket对象
server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)  #设置地址复用
server.bind(server_addr)  #绑定地址
server.listen(5)  #监听, 最大监听数为5
while True:
    client, client_addr = server.accept()  #接收TCP连接, 并返回新的套接字和地址
    print 'Connected by', client_addr
    while True :
        data = client.recv(BUF_SIZE)  #从客户端接收数据
        print data
        client.sendall(data)  #发送数据到客户端
server.close()

#客户端
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import sys
import socket


BUF_SIZE = 1024  #设置缓冲区的大小
server_addr = ('127.0.0.1', 8888)  #IP和端口构成表示地址
try : 
    client = socket.socket(socket.AF_INET, socket.SOCK_STREAM)  #返回新的socket对象
except socket.error, msg :
    print "Creating Socket Failure. Error Code : " + str(msg[0]) + " Message : " + msg[1]
    sys.exit()
client.connect(server_addr)  #要连接的服务器地址
while True:
    data = raw_input("Please input some string > ")  
    if not data :
        print "input can't empty, Please input again.."
        continue
    client.sendall(data)  #发送数据到服务器
    data = client.recv(BUF_SIZE)  #从服务器端接收数据
    print data
client.close()

UDP通信

sendto()
发送UDP数据,将数据发送到Socket
s.sendto(string[,flag],address)
s为socket.socket()返回的套接字对象
address : 指定远程地址, 形式为(ipaddr,port)的元组
flag : 提供有关消息的其他信息,通常可以忽略
返回值 : 发送的字节数。

recvfrom()
接受UDP套接字的数据,与recv()类似
s.recvfrom(bufsize[.flag])
返回值 : (data,address)元组, 其中data是包含接收数据的字符串,address是发送数据的套接字地址
bufsize : 指定要接收的数据大小
flag : 提供有关消息的其他信息,通常可以忽略

客户端服务器UDP连接

#服务器端
#!/usr/bin/env python
# -*- coding:utf-8 -*-
 
import socket
 
BUF_SIZE = 1024  #设置缓冲区大小
server_addr = ('127.0.0.1', 8888)  #IP和端口构成表示地址
server = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  #生成新的套接字对象
server.bind(server_addr)  #套接字绑定IP和端口
while True :
    print "waitting for data"
    data, client_addr = server.recvfrom(BUF_SIZE)  #从客户端接收数据
    print 'Connected by', client_addr, ' Receive Data : ', data
    server.sendto(data, client_addr)  #发送数据给客户端
server.close()
#客户端
#!/usr/bin/env python
# -*- coding:utf-8 -*-

import socket
import struct

BUF_SIZE = 1024  #设置缓冲区
server_addr = ('127.0.0.1', 8888)  #IP和端口构成表示地址
client = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)  #生成新的套接字对象

while True :
    data = raw_input('Please Input data > ')
    client.sendto(data, server_addr)  #向服务器发送数据
    data, addr = client.recvfrom(BUF_SIZE)  #从服务器接收数据
    print "Data : ", data
client.close()

posted @ 2018-01-23 13:41  blog_hfg  阅读(168)  评论(0)    收藏  举报