冰冻三尺非一日之寒-socket

第八章

  1. Socket语法及相关
  2. SocketServer实现多并发

socket概念:

网络上的两个程序通过一个双向的通信连接实现数据的交换,这个连接的一端称为一个socket。

Socket又称"套接字",应用程序通常通过"套接字"向网络发出请求或者应答网络请求。

根据连接启动的方式以及本地套接字要连接的目标,套接字之间的连接过程可以分为三个步骤:服务器监听,客户端请求,连接确认。

(1)服务器监听:是服务器端套接字并不定位具体的客户端套接字,而是处于等待连接的状态,实时监控网络状态。

(2)客户端请求:是指由客户端的套接字提出连接请求,要连接的目标是服务器端的套接字。为此,客户端的套接字必须首先描述它要连接的服务器的套接字,指出服务器端套接字的地址和端口号,然后就向服务器端套接字提出连接请求。

(3)连接确认:是指当服务器端套接字监听到或者说接收到客户端套接字的连接请求,它就响应客户端套接字的请求,建立一个新的线程,把服务端套接字的描述发给客户端,一旦客户端确认了此描述,连接就建立好了。而服务器端套接字继续处于监听状态,继续接收其他客户端套接字的连接请求。

 1 # Author:chen
 2 #_-_coding:utf-8_-_
 3 import socketserver
 4 import os
 5
 6 class MyTCPHandler(socketserver.BaseRequestHandler):
 7     flag=False
 8     def handle(self):
 9         while not self.flag:
10             msg=self.request.recv(1024)#接收客户端请求
11             #print(type(msg))
12             if not  msg:
13                 break
14             msg_n=msg.decode().split(‘>‘)
15             msg_type=msg_n[1]
16             if hasattr(self,msg_type):
17                 func=getattr(self,msg_type)
18                 func(msg_n)
19     def get_file(self,msg):  #回应客户端下载
20         file_name= msg[1]
21         if os.path.isfile(file_name):
22             file_size=os.path.getsize(file_name)
23             #print(‘file_size‘,type(file_size))
24             send_msg=‘yes:%s‘%(file_size)
25             self.request.send(send_msg.encode())
26             client_recv=self.request.recv(1024).decode()
27             if client_recv==‘ok‘:
28                 f=open(file_name,‘rb‘)
29                 send_size=0
30                 print(‘send_size‘, type(send_size))
31                 while not send_size==file_size:
32                     if file_size-send_size<=1024:
33                         self.request.send(f.read(file_size-send_size))
34                         send_size+=file_size-send_size
35                     else:
36                         self.request.send(f.read(1024))
37                         send_size+=1024
38                 else:
39                     print("为文件下载传输完成")
40                 f.close()
41             else:
42                 print(‘不予下载‘)
43     def put_file(self,msg):  #回应客户端上传
44         #client_res = self.request.recv(1024)
45         file_name,file_size=msg[1],int(msg[2])
46         if os.path.isfile(file_name):
47             f=open(‘%s.new‘ %(file_name),‘wb‘)
48         else:
49             f=open(file_name,‘wb‘)
50         self.request.send(b‘ok‘)#发送给客户端
51         recv_size=0
52         while not recv_size==file_size:
53             data=self.request.recv(1024)
54             #print(‘data:‘,data)
55             recv_size+=len(data)
56             f.write(data)
57         else:
58             print("文件上传完成")
59         f.close()
60 if __name__=="__main__":
61     HOST,PORT=‘0.0.0.0‘,9999
62     server=socketserver.ThreadingTCPServer((HOST,PORT),MyTCPHandler)
63     server.serve_forever()
 1 # Author:chen
 2 #_-_coding:utf-8_-_
 3 import socket,os
 4 class Myclient(object):
 5     user_dict={
 6         ‘help‘:‘help‘,
 7         ‘get‘:‘get_file‘,
 8         ‘put‘:‘put_file‘,
 9         ‘cd‘:‘cd‘,
10         ‘exit‘:‘exit‘
11     }
12     def __init__(self,host,port):
13         self.sock=socket.socket()
14         self.sock.connect((host,port))
15         self.flag=False
16         #if self.auth():
17         self.userinput()
18
19     def userinput(self):
20         while True:
21             u_input=input(‘please input your muan:‘)
22             if u_input==‘0‘:continue
23             user_input=u_input.split()
24             user_Type=u_input.split()[0]
25             print("客户端的请求是:",user_Type)
26             if user_Type in self.user_dict:
27                 func=getattr(self,self.user_dict[user_Type])
28                 func(user_input)
29             else:
30                 print("命令不存在,请重新输入")
31                 self.help()
32     def help(self):
33         print(self.user_dict)
34     def put_file(self,u):
35         if len(u)==2:
36             if os.path.isfile(u[1]):
37                 file_size=os.path.getsize(u[1])
38                 msg=‘put>%s>%s‘ % (u[1],file_size)
39                 self.sock.send(msg.encode())
40                 res_back=str(self.sock.recv(1024).decode())
41                 print("res_back:",res_back)
42                 if "ok" in res_back:
43                     f = open(u[1],‘rb‘)
44                     send_size=0
45                     while not send_size==file_size:
46                         if file_size-send_size<=1024:
47                             data=f.read(file_size-send_size)
48                             send_size+=file_size-send_size
49                         else:
50                             data=f.read(1024)
51                             send_size+=1024
52                         self.sock.send(data)
53                     else:
54                         print(‘文件上传完成‘)
55                     f.close()
56             else:
57                 print(‘文件不存在‘)
58     def get_file(self,u):
59         if len(u)==2:
60             msg="get>%s>2"%u[1]
61             self.sock.send(msg.encode())
62             res_back=self.sock.recv(1024).decode()
63             print(res_back)
64             if ‘yes‘in res_back:
65                 f=open(u[1],‘wb‘)
66                 file_size=int(res_back.split(‘:‘)[1])
67                 self.sock.send(b‘ok‘)
68                 size_revc=0
69                 while not size_revc==file_size:
70                     data=self.sock.recv(file_size-size_revc)
71                     size_revc+=len(data)
72                     f.write(data)
73                 else:
74                     print(‘下载完成‘)
75                 f.close()
76         else:
77             print(‘+++++‘)
78 if __name__=="__main__":
79     c=Myclient(‘localhost‘,9999)

comefrom http://www.cnblogs.com/alex3714/articles/5227251.html

socket.getaddrinfo(hostportfamily=0type=0proto=0flags=0) #获取要连接的对端主机地址

sk.bind(address)

  s.bind(address) 将套接字绑定到地址。address地址的格式取决于地址族。在AF_INET下,以元组(host,port)的形式表示地址。

sk.listen(backlog)

  开始监听传入连接。backlog指定在拒绝连接之前,可以挂起的最大连接数量。

backlog等于5,表示内核已经接到了连接请求,但服务器还没有调用accept进行处理的连接个数最大为5
      这个值不能无限大,因为要在内核中维护连接队列

sk.setblocking(bool)

  是否阻塞(默认True),如果设置False,那么accept和recv时一旦无数据,则报错。

sk.accept()

  接受连接并返回(conn,address),其中conn是新的套接字对象,可以用来接收和发送数据。address是连接客户端的地址。

  接收TCP 客户的连接(阻塞式)等待连接的到来

sk.connect(address)

  连接到address处的套接字。一般,address的格式为元组(hostname,port),如果连接出错,返回socket.error错误。

sk.connect_ex(address)

  同上,只不过会有返回值,连接成功时返回 0 ,连接失败时候返回编码,例如:10061

sk.close()

  关闭套接字

sk.recv(bufsize[,flag])

  接受套接字的数据。数据以字符串形式返回,bufsize指定最多可以接收的数量。flag提供有关消息的其他信息,通常可以忽略。

sk.recvfrom(bufsize[.flag])

  与recv()类似,但返回值是(data,address)。其中data是包含接收数据的字符串,address是发送数据的套接字地址。

sk.send(string[,flag])

  将string中的数据发送到连接的套接字。返回值是要发送的字节数量,该数量可能小于string的字节大小。即:可能未将指定内容全部发送。

sk.sendall(string[,flag])

  将string中的数据发送到连接的套接字,但在返回之前会尝试发送所有数据。成功返回None,失败则抛出异常。

内部通过递归调用send,将所有内容发送出去。

sk.sendto(string[,flag],address)

  将数据发送到套接字,address是形式为(ipaddr,port)的元组,指定远程地址。返回值是发送的字节数。该函数主要用于UDP协议。

sk.settimeout(timeout)

  设置套接字操作的超时期,timeout是一个浮点数,单位是秒。值为None表示没有超时期。一般,超时期应该在刚创建套接字时设置,因为它们可能用于连接的操作(如 client 连接最多等待5s )

sk.getpeername()

  返回连接套接字的远程地址。返回值通常是元组(ipaddr,port)。

sk.getsockname()

  返回套接字自己的地址。通常是一个元组(ipaddr,port)

sk.fileno()

  套接字的文件描述符

socket.sendfile(fileoffset=0count=None)

     发送文件 ,但目前多数情况下并无什么卵用。

常用函数(来自百度百科):

创建

函数原型:

int socket(int domain, int type, int protocol);

参数说明:
  

domain:协议域,又称协议族
(family)。常用的协议族有AF_INET、AF_INET6、AF_LOCAL(或称AF_UNIX,Unix域Socket)、
AF_ROUTE等。协议族决定了socket的地址类型,在通信中必须采用对应的地址,如AF_INET决定了要用ipv4地址(32位的)与端口号
(16位的)的组合、AF_UNIX决定了要用一个绝对路径名作为地址。

type:指定Socket类型。常用的
socket类型有SOCK_STREAM、SOCK_DGRAM、SOCK_RAW、SOCK_PACKET、SOCK_SEQPACKET等。流式
Socket(SOCK_STREAM)是一种面向连接的Socket,针对于面向连接的TCP服务应用。数据报式Socket(SOCK_DGRAM)
是一种无连接的Socket,对应于无连接的UDP服务应用。

protocol:指定协议。常用协议有IPPROTO_TCP、IPPROTO_UDP、IPPROTO_STCP、IPPROTO_TIPC等,分别对应TCP传输协议、UDP传输协议、STCP传输协议、TIPC传输协议。

注意:1.type和protocol不可以随意组合,如SOCK_STREAM不可以跟IPPROTO_UDP组合。当第三个参数为0时,会自动选择第二个参数类型对应的默认协议。

2.WindowsSocket下protocol参数中不存在IPPROTO_STCP

绑定

函数原型:

int bind(SOCKET socket, const struct sockaddr* address, socklen_t address_len);

参数说明:

socket:是一个套接字描述符。

address:是一个sockaddr结构指针,该结构中包含了要结合的地址和端口号。

address_len:确定address缓冲区的长度。

返回值:

如果函数执行成功,返回值为0,否则为SOCKET_ERROR。

接收

函数原型:

int recv(SOCKET socket, char FAR* buf, int len, int flags);

参数说明:
  

socket:一个标识已连接套接字的描述字。

buf:用于接收数据的缓冲区。

len:缓冲区长度。

flags:指定调用方式。取值:MSG_PEEK 查看当前数据,数据将被复制到缓冲区中,但并不从输入队列中删除;MSG_OOB 处理带外数据。

返回值:

若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,应用程序可通过WSAGetLastError()获取相应错误代码。

函数原型:

ssize_t recvfrom(int sockfd, void buf, int len, unsigned int flags, struct socketaddr* from, socket_t* fromlen);

参数说明:

sockfd:标识一个已连接套接口的描述字。

buf:接收数据缓冲区

len:缓冲区长度。

flags:调用操作方式。是以下一个或者多个标志的组合体,可通过or操作连在一起:

(1)MSG_DONTWAIT:操作不会被阻塞;

(2)MSG_ERRQUEUE:
指示应该从套接字的错误队列上接收错误值,依据不同的协议,错误值以某种辅佐性消息的方式传递进来,使用者应该提供足够大的缓冲区。导致错误的原封包通过
msg_iovec作为一般的数据来传递。导致错误的数据报原目标地址作为msg_name被提供。错误以sock_extended_err结构形态被
使用。

(3)MSG_PEEK:指示数据接收后,在接收队列中保留原数据,不将其删除,随后的读操作还可以接收相同的数据。

(4)MSG_TRUNC:返回封包的实际长度,即使它比所提供的缓冲区更长, 只对packet套接字有效。

(5)MSG_WAITALL:要求阻塞操作,直到请求得到完整的满足。然而,如果捕捉到信号,错误或者连接断开发生,或者下次被接收的数据类型不同,仍会返回少于请求量的数据。

(6)MSG_EOR:指示记录的结束,返回的数据完成一个记录。

(7)MSG_TRUNC:指明数据报尾部数据已被丢弃,因为它比所提供的缓冲区需要更多的空间。
  

/*(MSG_TRUNC使用错误,4才是MSG_TRUNC的正确解释)*/

(8)MSG_CTRUNC:指明由于缓冲区空间不足,一些控制数据已被丢弃。

(9)MSG_OOB:指示接收到out-of-band数据(即需要优先处理的数据)。

(10)MSG_ERRQUEUE:指示除了来自套接字错误队列的错误外,没有接收到其它数据。

from:(可选)指针,指向装有源地址的缓冲区。

fromlen:(可选)指针,指向from缓冲区长度值。

发送

函数原型:

int sendto( SOCKET s, const char FAR* buf, int size, int flags, const struct sockaddr FAR* to, int tolen);

参数说明:

s套接字

buf:待发送数据的缓冲区

size:缓冲区长度

flags:调用方式标志位, 一般为0, 改变Flags,将会改变Sendto发送的形式

addr:(可选)指针,指向目的套接字的地址

tolen:addr所指地址的长度

返回值:

如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR。

接收连接请求

函数原型:

int accept( int fd, struct socketaddr* addr, socklen_t* len);

参数说明:

fd:套接字描述符。

addr:返回连接着的地址

len:接收返回地址的缓冲区长度

返回值:

成功返回客户端的文件描述符,失败返回-1。

时间: 2024-10-12 13:55:53

冰冻三尺非一日之寒-socket的相关文章

冰冻三尺非一日之寒之产品观

我不是产品经理,是单纯的码农.从事两年多的互联网行业,基本上算是熟人吧.最近,这两年多,我倍受中国互联网的变革力--互联网颠覆论.我不知道怎么样才算颠覆.在互联网订餐,线下送餐,所谓的O2O订餐就颠覆了传统的快餐业务?我只知道在我们公司附近,有家叫极客的餐厅,最近在低价转让. 极客餐厅,极客在哪里?或许有人说,极客在体验,O2O啊!O2O只是一个方式,个人感觉谈不上颠覆.我觉得餐厅的体验在于:饭菜的美味.饭菜的安全.饭菜的营养.用餐舒适.没有美味的饭菜,味同爵蜡,尤其是上班人员天天吃那几款饭菜,

冰冻三尺非一日之寒--面向对象

第七章: 面向对象高级语法部分 静态方法.类方法.属性方法 类的特殊方法 反射 异常处理 Socket开发基础 面向对象高级语法部分 静态方法 通过@staticmethod装饰器即可把其装饰的方法变为一个静态方法,什么是静态方法呢?其实不难理解,普通的 方法,可以在实例化后直接调用,并且在方法里可以通过self.调用实例变量或类变量,但静态方法是不可以访问实例变量或类变量的,一个不能访问实例变量 和类变量的方法,其实相当于跟类本身已经没什么关系了,它与类唯一的关联就是需要通过类名来调用这个方法

冰冻三尺非一日之寒-来一个堡垒机

第十三章   堡垒机 1.堡垒机的概念 2.堡垒机的实现 概念: 背景,公司为了主机系统的管理和安全,更有效的工作,产生的一种工作模式,往往一个公司有很多台服务器,这些服务器又有许多人需要去操作,运维.开发.测试等.人多 手杂,谁操作了什么,导致了什么问题,用户的管理.主机的管理,都需要高效的实现,堡垒机实现了这些管理上的方便. 直接说事,堡垒机是建立在工作

冰冻三尺非一日之寒--循序渐进

第三章 1.集合的操作:                                        2 .文件操作: 3.字符编码与解码: 1.集合 集合是一个无序的.不重复的数据组合. 集合的用途: 1.去重,将列表变成集合后,会自动去重 2.集合间的关系,例如:集合的交集.并集,子集关系,对于数据的存储.操作有一定的优势 去重: 去重

冰冻三尺非一日之寒之闭门打坐

第二章 1.列表的操作                                  2.元组的操作 3.字符串操作                                  4.字典的操作  The reason why people give up so quickly is because they look at how far they still have to go, instead of how far they have come ♣列表的操作: 列表:列表用于存储

冰冻三尺非一日之寒--还是web

第十五章  css     javascript(js) 1.css重用                <style>            如果整个页面的宽度 > 900px时:            {                .c{                   共有                 }                .c1{                    独有                }            }             

16年随笔

近来,在带一个业务系统.这个系统涉及到产品.物料.库存等.说复杂不复杂,说简单也不简单.但就是这样一个项目,我真的清楚了以前另一个客户说的话,我们就一直都在填坑,更有人还要把你往坑里推. 今天,我要说的有三点:    1. 软件设计    2 UI设计    3.做一个专业的从业人员 设计 设计这个词其实一个很严肃的词.因为,我们目前是处于一个设计的时代,设计已经融入在我们生活的方方面面.    我今天要谈到的设计主要分为两块,一块是软件设计,另一块是UI设计.我们先来聊聊软件设计. 一. 软件

20150716-陈鹏-Roc

今日收获:总体来说,今天的表现尚可,和搭档崔璨的配合也很不错,希望再接再厉.在这个过程当中,我们基本上能够完整.流利地练习两段对话,互相纠正对方的错误.万事开头难,后面我想我们会变现得更好.同时,我也找了崔宇尭.胡敏.谢霞.苏圣宏等伙伴进行了练习,从他们身上也学到了很多. 需要提高点:当然,我们团队的练习的流畅度还有待提高,发音.连读.表情.动作等掌握得还不是很好,接下来将会进一步进行落实.积极向优秀的同学学习,当然练习的方式方法我们还在进一步的摸索当中. 明日计划:练习.排练今天的文本,争取做

JavaWeb网站技术架构

JavaWeb网站技术架构总结 题记 工作也有几多年了,无论是身边遇到的还是耳间闻到的,多多少少也积攒了自己的一些经验和思考,当然,博主并没有太多接触高大上的分布式架构实践,相对比较零碎,随时补充(附带架构装逼词汇). 俗话说的好,冰冻三尺非一日之寒,滴水穿石非一日之功,罗马也不是一天就建成的,当然对于我们开发人员来说,一个好的架构也不是一蹴而就的. 初始搭建 开始的开始,就是各种框架一搭,然后扔到Tomcat容器中跑就是了,这时候我们的文件,数据库,应用都在一个服务器上. 服务分离 随着系统的