日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

练习题|网络编程-socket开发

發(fā)布時間:2023/12/6 编程问答 48 豆豆
生活随笔 收集整理的這篇文章主要介紹了 练习题|网络编程-socket开发 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

原文:https://www.cnblogs.com/shengyang17/p/8822745.html

1、什么是C/S架構(gòu)?

  C指的是client(客戶端軟件),S指的是Server(服務端軟件),C/S架構(gòu)的軟件,實現(xiàn)服務端軟件與客戶端軟件基于網(wǎng)絡通信。

2、互聯(lián)網(wǎng)協(xié)議是什么?分別介紹五層協(xié)議中每一層的功能?

  互聯(lián)網(wǎng)協(xié)議就是計算機界通用的語言;互聯(lián)網(wǎng)協(xié)議分為osi七層或tcp/ip五層或tcp/ip四層;

物理層功能:主要是基于電器特性發(fā)送高低電壓(電信號),高電壓對應數(shù)字1,低電壓對應數(shù)字0。

數(shù)據(jù)鏈路層的功能:定義了電信號的分組方式按照以太網(wǎng)協(xié)議;一組電信號構(gòu)成一個數(shù)據(jù)包,叫做一組數(shù)據(jù)‘幀’;每一數(shù)據(jù)幀分成:報頭head和數(shù)據(jù)data兩部分。head前六個字節(jié)和后六個字節(jié)是mac地址,基于mac地址來標示對方;在局域網(wǎng)內(nèi)以廣播的方式工作。

網(wǎng)絡層功能:引入一套新的地址用來區(qū)分不同的廣播域/子網(wǎng),這套地址即網(wǎng)絡地址。

傳輸層功能:建立端口到端口的通信,端口即應用程序與網(wǎng)卡關聯(lián)的編號。tcp和udp

應用層功能:有自己的協(xié)議如http、ftp協(xié)議,跑應用軟件。

?

3、基于tcp協(xié)議通信,為何建立鏈接需要三次握手,而斷開鏈接卻需要四次揮手?

tcp協(xié)議,客戶端給服務端發(fā)一次消息,服務端要回應下并且給發(fā)給客戶端,然后客戶端再發(fā)給服務端,中間兩步回應下+給客戶端發(fā)消息可以合成一步,鏈接建立完成也就是三次握手;客戶端說要斷開鏈接PIN=1,服務端確認下ack=1,客戶端接收到了,這條管道就斷開了,服務端要斷開發(fā)PIN=1,客戶端回一個ack=1,管道就斷開了。

客戶端說把數(shù)據(jù)傳完了,服務端不一定傳完數(shù)據(jù)了,中間那兩步不能合成一步,所以斷開鏈接需要四次揮手。

4、為何基于tcp協(xié)議的通信比基于udp協(xié)議的通信更可靠?

  ?tcp協(xié)議一定是先建好雙向鏈接,發(fā)一個數(shù)據(jù)包要得到確認才算發(fā)送完成,沒有收到就一直給你重發(fā);udp協(xié)議沒有鏈接存在,udp直接丟數(shù)據(jù),不管你有沒有收到。

?

5、?流式協(xié)議指的是什么協(xié)議,數(shù)據(jù)報協(xié)議指的是什么協(xié)議?

? 流式協(xié)議指的是tcp協(xié)議,數(shù)據(jù)報協(xié)議指的是udp協(xié)議

?

6、什么是socket?簡述基于tcp協(xié)議的套接字通信流程?

Socket是應用層與TCP/IP協(xié)議族通信的中間軟件抽象層,它是一組接口。在設計模式中,Socket其實就是一個門面模式,它把復雜的TCP/IP協(xié)議族隱藏在Socket接口后面,對用戶來說,一組簡單的接口就是全部。?

?服務端先初始化Socket實例化一個類拿到對象(才能調(diào)用下面的接口),然后綁定IP端口(bind),監(jiān)聽(listen)就是說客戶端可以來連我了,調(diào)用accept接收鏈接;這時客戶端初始化一個socket,然后connect與服務端建立好雙向鏈接與accept對應。客戶端發(fā)送請求數(shù)據(jù),服務端處理請求并給客戶端回應數(shù)據(jù),這樣一個通信循環(huán);最后關閉套接字,一次交互結(jié)束。

?

7、什么是粘包? socket 中造成粘包的原因是什么? 哪些情況會發(fā)生粘包現(xiàn)象?

?如客戶端只recv(1024), 可結(jié)果比1024長那怎么辦,只好在服務器端的IO緩沖區(qū)里把客戶端還沒收走的暫時存下來,等客戶端下次再來收,所以當客戶端第2次調(diào)用recv(1024)就會首先把上次沒收完的數(shù)據(jù)先收下來,再收df命令的結(jié)果。

這個現(xiàn)象叫做粘包,就是指兩次結(jié)果粘到一起了。它的發(fā)生主要是因為socket緩沖區(qū)導致的。

所謂粘包問題原因:(1)主要還是因為接收方不知道消息之間的界限,不知道一次性提取多少字節(jié)的數(shù)據(jù)所造成的。(2)發(fā)送方引起的粘包是由TCP協(xié)議本身造成的,TCP為提高傳輸效率,發(fā)送方往往要收集到足夠多的數(shù)據(jù)后才發(fā)送一個TCP段。若連續(xù)幾次需要send的數(shù)據(jù)都很少,通常TCP會根據(jù)優(yōu)化算法把這些數(shù)據(jù)合成一個TCP段后一次發(fā)送出去,這樣接收方就收到了粘包數(shù)據(jù)。

發(fā)生粘包的情況:(1)發(fā)送端需要等緩沖區(qū)滿才發(fā)送出去,造成粘包(發(fā)送數(shù)據(jù)時間間隔很短,數(shù)據(jù)了很小,會合到一起,產(chǎn)生粘包)(2)接收方不及時接收緩沖區(qū)的包,造成多個包接收(客戶端發(fā)送了一段數(shù)據(jù),服務端只收了一小部分,服務端下次再收的時候還是從緩沖區(qū)拿上次遺留的數(shù)據(jù),產(chǎn)生粘包)

?

8、基于socket開發(fā)一個聊天程序,實現(xiàn)兩端互相發(fā)送和接收消息

server

#Author:Kris# import socket # # HOST = '' # Symbolic name meaning all available interfaces # PORT = 50007 # Arbitrary non-privileged port # # sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # sock_server.bind((HOST, PORT)) # # sock_server.listen(1) #開始監(jiān)聽,1代表在允許有一個連接排隊,更多的新連接連進來時就會被拒絕 # conn, addr = sock_server.accept() #阻塞直到有連接為止,有了一個新連接進來后,就會為這個請求生成一個連接對象 # # with conn: # print('Connected by', addr) # while True: # data = conn.recv(1024) #接收1024個字節(jié) # print("server recv:",conn.getpeername(), data.decode()) # if not data: break #收不到數(shù)據(jù),就break # conn.sendall(data) #把收到的數(shù)據(jù)再全部返回給客戶端 import socket HOST = '' # Symbolic name meaning all available interfaces PORT = 50007 # Arbitrary non-privileged port sock_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM) sock_server.bind((HOST, PORT)) sock_server.listen(1) #開始監(jiān)聽,1代表在允許有一個連接排隊,更多的新連接連進來時就會被拒絕 conn, addr = sock_server.accept() #阻塞直到有連接為止,有了一個新連接進來后,就會為這個請求生成一個連接對象 with conn: print('Connected by', addr) while True: data = conn.recv(1024) #接收1024個字節(jié) print("recv from Alex:",conn.getpeername(), data.decode()) if not data: break #收不到數(shù)據(jù),就break response = input(">>>").strip() conn.send(response.encode()) print("send to alex:",response)

client

#Author:Krisimport socketHOST = 'localhost' # The remote host PORT = 50007 # The same port as used by the server client = socket.socket(socket.AF_INET, socket.SOCK_STREAM) client.connect((HOST, PORT)) while True: msg = input(">>>:").strip() if len(msg) == 0:continue client.sendall(msg.encode()) #發(fā)送用戶輸入的數(shù)據(jù),必須是bytes模式 data = client.recv(1024) print('Received',data.decode()) #收到服務器的響應后,decode一下

? ?

9、基于tcp socket,開發(fā)簡單的遠程命令執(zhí)行程序,允許用戶執(zhí)行命令,并返回結(jié)果

?server

import socket import subprocessphone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) # phone.setsockopt(socket.SOL_SOCKET,socket.SO_REUSEADDR,1) phone.bind(('127.0.0.1',9901)) #0-65535:0-1024給操作系統(tǒng)使用 phone.listen(5) print('starting...') while True: # 鏈接循環(huán) conn,client_addr=phone.accept() print(client_addr) while True: #通信循環(huán) try: #1、收命令 cmd=conn.recv(1024) if not cmd:break #適用于linux操作系統(tǒng) #2、執(zhí)行命令,拿到結(jié)果 obj = subprocess.Popen(cmd.decode('utf-8'), shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout=obj.stdout.read() #它就是bytes格式;正確的 stderr=obj.stderr.read() #錯誤的結(jié)果 #3、把命令的結(jié)果返回給客戶端 print(len(stdout)+len(stderr)) conn.send(stdout+stderr) #+是一個可以優(yōu)化的點,申請一個新的內(nèi)存空間 except ConnectionResetError: #適用于windows操作系統(tǒng) break conn.close() phone.close()

client

import socket phone=socket.socket(socket.AF_INET,socket.SOCK_STREAM) phone.connect(('127.0.0.1',9901)) while True: #1、發(fā)命令 cmd=input('>>: ').strip() #ls /etc if not cmd:continue phone.send(cmd.encode('utf-8')) #2、拿命令的結(jié)果,并打印 data=phone.recv(1024) #1024是一個坑 print(data.decode('gbk')) phone.close()

?

10、基于tcp協(xié)議編寫簡單FTP程序,實現(xiàn)上傳、下載文件功能,并解決粘包問題

?服務端

import socket import struct import json import subprocess import osclass MYTCPServer:address_family = socket.AF_INET socket_type = socket.SOCK_STREAM allow_reuse_address = False max_packet_size = 8192 coding='utf-8' request_queue_size = 5 server_dir='file_upload' def __init__(self, server_address, bind_and_activate=True): """Constructor. May be extended, do not override.""" self.server_address=server_address self.socket = socket.socket(self.address_family, self.socket_type) if bind_and_activate: try: self.server_bind() self.server_activate() except: self.server_close() raise def server_bind(self): """Called by constructor to bind the socket. """ if self.allow_reuse_address: self.socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) self.socket.bind(self.server_address) self.server_address = self.socket.getsockname() def server_activate(self): """Called by constructor to activate the server. """ self.socket.listen(self.request_queue_size) def server_close(self): """Called to clean-up the server. """ self.socket.close() def get_request(self): """Get the request and client address from the socket. """ return self.socket.accept() def close_request(self, request): """Called to clean up an individual request.""" request.close() def run(self): while True: self.conn,self.client_addr=self.get_request() print('from client ',self.client_addr) while True: try: head_struct = self.conn.recv(4) if not head_struct:break head_len = struct.unpack('i', head_struct)[0] head_json = self.conn.recv(head_len).decode(self.coding) head_dic = json.loads(head_json) print(head_dic) #head_dic={'cmd':'put','filename':'a.txt','filesize':123123} cmd=head_dic['cmd'] if hasattr(self,cmd): func=getattr(self,cmd) func(head_dic) except Exception: break def put(self,args): file_path=os.path.normpath(os.path.join( self.server_dir, args['filename'] )) filesize=args['filesize'] recv_size=0 print('----->',file_path) with open(file_path,'wb') as f: while recv_size < filesize: recv_data=self.conn.recv(self.max_packet_size) f.write(recv_data) recv_size+=len(recv_data) print('recvsize:%s filesize:%s' %(recv_size,filesize)) tcpserver1=MYTCPServer(('127.0.0.1',8080)) tcpserver1.run()

客戶端

import socket import struct import json import osclass MYTCPClient:address_family = socket.AF_INET socket_type = socket.SOCK_STREAM allow_reuse_address = False max_packet_size = 8192 coding='utf-8' request_queue_size = 5 def __init__(self, server_address, connect=True): self.server_address=server_address self.socket = socket.socket(self.address_family, self.socket_type) if connect: try: self.client_connect() except: self.client_close() raise def client_connect(self): self.socket.connect(self.server_address) def client_close(self): self.socket.close() def run(self): while True: inp=input(">>: ").strip() if not inp:continue l=inp.split() cmd=l[0] if hasattr(self,cmd): func=getattr(self,cmd) func(l) def put(self,args): cmd=args[0] filename=args[1] if not os.path.isfile(filename): print('file:%s is not exists' %filename) return else: filesize=os.path.getsize(filename) head_dic={'cmd':cmd,'filename':os.path.basename(filename),'filesize':filesize} print(head_dic) head_json=json.dumps(head_dic) head_json_bytes=bytes(head_json,encoding=self.coding) head_struct=struct.pack('i',len(head_json_bytes)) self.socket.send(head_struct) self.socket.send(head_json_bytes) send_size=0 with open(filename,'rb') as f: for line in f: self.socket.send(line) send_size+=len(line) print(send_size) else: print('upload successful') client=MYTCPClient(('127.0.0.1',8080)) client.run()

?

?

11、基于udp協(xié)議編寫程序,實現(xiàn)功能

  • 執(zhí)行指定的命令,讓客戶端可以查看服務端的時間

  • 執(zhí)行指定的命令,讓客戶端可以與服務的的時間同步

  • ?server

    import socket import subprocess import timeserver = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) server.bind(('127.0.0.1', 8080)) while True: data, client_addr = server.recvfrom(1024) print(data, client_addr) obj = subprocess.Popen(data.decode('utf-8'),shell=True, # time 命令在windows 下不能用 stdout=subprocess.PIPE, stderr=subprocess.PIPE) stdout = obj.stdout.read() stderr = obj.stderr.read() print(stdout+stderr) server.sendto(stdout+stderr,client_addr) if data.decode('utf-8') == 'time': str_time = time.strftime('%Y-%m-%d %H:%M:%S', time.localtime()) # str_time = '2017-01-01 00:00:00' server.sendto(str_time.encode('gbk'), client_addr) server.close()

    client

    import socket import os import time client = socket.socket(socket.AF_INET,socket.SOCK_DGRAM) while True:msg = input('>>>:').strip() client.sendto(msg.encode('utf-8'),('127.0.0.1',8080)) data,server_addr = client.recvfrom(1024) print(data.decode('utf-8'),server_addr) localtime = time.localtime() os.system("date %d-%d-%d" % (localtime.tm_year, localtime.tm_mon, localtime.tm_mday)) # 設置日期 os.system("time %d:%d:%d.0" % (localtime.tm_hour, localtime.tm_min, localtime.tm_sec)) # 設置時間 client.close()

    ?

    分類: 練習

    轉(zhuǎn)載于:https://www.cnblogs.com/fmgao-technology/p/9150284.html

    總結(jié)

    以上是生活随笔為你收集整理的练习题|网络编程-socket开发的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

    如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。