【计算机网络】4 Socket网络编程

这篇具有很好参考价值的文章主要介绍了【计算机网络】4 Socket网络编程。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

目录

写在前面的话

概览

环境

URL请求程序:

2. 系统时间查询

服务端

T_TCPServer.py代码

客户端

T_TCPClient.py代码

运行效果

3. 网络文件传输

服务端

TF_TCPServer.py代码

运行效果(后面加了远程功能,效果图暂时还在本地)

4. 网络聊天室

服务端

UDPServer.py代码

客户端

UDPClient.py代码

运行效果

开启服务器,jennie客户端和john客户端陆续加入群聊

聊天(4栏:服务器,mike,  john,  jennie)

mike回复消息同样被转发给全部用户

用户退出

问题及解决:

URL 请求程序

系统时间查询

网络文件传输

网络聊天室

实验心得体会

总结


写在前面的话

这个危,开学初老师曾觉得这个编程实验可能会劝退我这个小白。emmm熬过来了。上学期有老师说得先自学下Java搞这个,emmm寒假整c++一些个小系统,Java纯纯学点点写几个基本小系统罢了觉得不太可。幸好我的班用python。前年学了点毛皮捡捡还能用,1周速成python,再1周速成个多人聊天室,爬过来就可。

概览

▪ UDP与TCP套接字的区别

▪ UDP和TCP套接字编程方法

▪ 简单网络应用的编程思路

▪ 网络编程相关的一些库

1. URL 请求程序

2. 系统时间查询

3. 网络文件传输

4. 网络聊天室

环境

▪ 具有Internet连接的主机, VScode(直接在其终端运行),PowerShell

▪ 编程语言: python

  1. URL请求程序:

请求一个网页,并存储为html文件,计算所请求网页的大小。打印所请求网页的URL、存储文件名、文件大小等信息。(图1 2)

【计算机网络】4 Socket网络编程

Figure 1 url请求程序

调用requests库请求对应url并保存。将url切片获得文件名,通过os库获得文件大小。

【计算机网络】4 Socket网络编程

Figure 2 保存下来HTML网页文件

2. 系统时间查询

实现一个基于客户/服务器的系统时间查询程序。

传输层使用TCP

交互过程

1) 客户端向服务器端发送字符串Time

2) 服务器端收到该字符串后,返回当前系统时间。

3) 客户端向服务器端发送字符串Exit

4) 服务器端返回Bye,然后结束TCP连接。

  • 服务端

服务端创建TCP协议的socket套接字进程,端口号为12000,并保持监听状态。一旦收到客户端的连接就从socket套接字中获取客户端发送的消息。 如果收到无效信息回复提示。直到Exit才停止收发并断开连接。并可以与另外的客户端通信。

T_TCPServer.py代码

from socket import *
import time#获得系统时间

serverPort = 12000
serverSocket = socket(AF_INET, SOCK_STREAM)
serverSocket.bind(('', serverPort))
serverSocket.listen(1)

print('----------------------------------')
print('服务器已经准备好连接了')
print('服务器地址为:',serverSocket.getsockname())

while True:
    connectionSocket, addr = serverSocket.accept()
    print('----------------------------------')
    print('接收到一个新连接')
    print('连接地址为:',serverSocket.getsockname())
    print('客户端地址为:',addr)

    while True:
        request = connectionSocket.recv(1024).decode()
        if request == '':
            continue
        print('收到请求: ', request)
        
        if request == 'Time':
            # 格式化成2016-03-20 11:45:39形式
            now = time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()) 
            print('发送响应:',now)
            connectionSocket.send(('收到当前服务器上系统时间为:'+now).encode())
        elif request == 'Exit':
            print('发送响应:Bye')
            connectionSocket.send('收到回复:Bye'.encode())
            connectionSocket.close()#结束TCP连接
            break#跳出循环
        else:
            print('发送响应:输入有误,请重新输入')
            connectionSocket.send('输入有误,请重新输入'.encode())
  • 客户端

考虑远程实现,需要手动输入服务端IP及端口号12000。通过ipconfig查询,本机IP:192.168.0.107。

T_TCPClient.py代码

from socket import *

clientSocket = socket(AF_INET, SOCK_STREAM)
print('1个客户端正在运行')

serverName = input('请输入要连接的服务端IP:')
serverPort = int(input('请输入要连接的服务端的端口号:'))

clientSocket.connect((serverName, serverPort))
print('客户端地址:',clientSocket.getsockname())
print('连接到',clientSocket.getpeername())

while True:
    request = input('发送一条请求:')
    clientSocket.send(request.encode())#请求发送
    modifiedSentence = clientSocket.recv(1024)#回复报文
    print(modifiedSentence.decode())#打印回复
    
    if request == 'Exit':
        clientSocket.close()
        break
  • 运行效果

先启动服务端,再启动客户端A连接并交互,发送“Time”时服务端回复系统时间,发送“Exit”时回复“Bye”并断开与客户端的连接。发送命令时无效,并回复提示信息。断开与客户端A的连接后服务端还可以继续与其他客户端通信。(图3 

【计算机网络】4 Socket网络编程

Figure 3 系统时间查询

3. 网络文件传输

实现一个基于客户/服务器的网络文件传输程序。

传输层使用TCP

交互过程

1) 客户端从用户输入获得待请求的文件名。

2) 客户端向服务器端发送文件名。

3) 服务器端收到文件名后,传输文件。

4) 客户端接收文件,重命名并存储在硬盘。

  • 服务端

同样服务端需要先创建TCP协议下的与固定端口号绑定的进程套接字socket,并保持监听状态等待与客户端连接。每次发送文件分组64字节,直至发送完毕后关闭连接。引入os库来查看文件是否存在,并返回提示。

TF_TCPServer.py代码

from socket import *

clientSocket = socket(AF_INET, SOCK_STREAM)
print('-----------------------------')
print('客户端正在运行')

serverName = input('请输入要连接的服务端IP:')
serverPort = int(input('请输入要连接的服务端的端口号:'))

clientSocket.connect((serverName, serverPort))
print('客户端地址:',clientSocket.getsockname())
print('连接到',clientSocket.getpeername())

filename = input('请输入所请求的文件名:')
clientSocket.send(filename.encode())#请求发送
print('已发送文件名 【', filename, '】 至服务器')

modifiedSentence = clientSocket.recv(1024).decode()#回复报文
print(modifiedSentence)#打印回复报文

if modifiedSentence == 'ok':
    file_size = clientSocket.recv(1024).decode()#获得文件大小
    print('文件大小为:', file_size, ' 字节')#打印回复报文

    print('-----------------------------')
    f = open(filename, 'wb')#新建待写入文件

    while True:
        r = clientSocket.recv(64)#每次接收64字节报文

        if len(r)==0:
            print('-----------------------------')
            print('1个名为 【', filename, '】、大小为 ', file_size, ' 字节的文件已被保存')
            print('接收完毕!')
            print('-----------------------------')
            break#发完退出

        print('收到 ', len(r), ' 字节的数据')
        f.write(r)#写入文件

clientSocket.close()
  • 运行效果(后面加了远程功能,效果图暂时还在本地)

先启动好服务器并保持监听状态等待连接,在启动客户端与服务器建立连接(TCP),发送所请求传输的文件名。服务器收到文件名后利用os库查询是否存在文件。文件不存在返回提示信息并断开连接。文件存在则开始传输每次64字节的文件分组,直至检测到待传输文件分组为0字节时停止传输,并提示传输完毕信息,断开连接。客户端在每次收到文件分组的时候将其存于客户端本地的同名文件。直至所收到分组为0字节时确定接收完毕,打印提示信息并关闭连接。

【计算机网络】4 Socket网络编程

4. 网络聊天室

实现一个基于客户/服务器的网络聊天程序。

要求实现多个用户的群聊。要求客户端打印聊天消息,服务器打印系统信息。

传输层使用UDP

不要求实现GUI界面。

  • 服务端

服务器程序维护一个聊天室用户字典列表userList来了解聊天室里有哪些用户(客户端),映射关系为IP:name。新用户到达时加进来,旧用户离开时删除。每次用户发来消息,通过知道聊天室里有哪些用户(客户端),确定该用户是否是新用户。

需要实现的群聊功能是一个用户发消息,所有用户都能收到。相应地,一个客户端把聊天消息发给服务器,服务器再将收到的消息转发给所有客户端。所以在服务端需要有一个SendUser() 函数来实现每次收到信息转发给用户表内全部用户相同信息的功能。

服务端创建与固定端口号绑定的socket并开启等待消息,消息有3类:新用户加入的昵称消息,‘quit’用户退出群聊消息,一般聊天消息。

第一类为新用户加入的昵称消息。如果所收到客户端的IP是用户字典里不存在的,则可判断为新用户且发送过来的消息为他的昵称。回复欢迎并将新用户加入消息转发给全部用户(用户字典里的)。

第二类“quit”消息。当用户发送“quit”时,用户退出群聊,服务端断开与其的连接并将该消息转发给全部用户。

第三类一般聊天消息。如果所接受消息并非上面2类,就可判断其为一般聊天消息,服务器需要将其加上用户名转发给用户字典里的全部用户。用户名可通过消息的IP地址在用户字典里查询到。

UDPServer.py代码

from socket import *

userList = {} #创建userList(map ip:name)

def SendUsers(userList, data):#将数据发送给全部用户
    for user in userList:
        serverSocket.sendto(data.encode(), user)
        print('发送给 ', user, ' ---> ',data)

serverPort = 12000
serverSocket = socket(AF_INET, SOCK_DGRAM)
serverSocket.bind(('', serverPort))
print('服务器已经准备好接收了')

while True:
    message, clientAddress = serverSocket.recvfrom(2048)
    m = message.decode()#解码报文
    print('收到来自 ', clientAddress, ' 的信息 ---> ', m)

    #如果所接收用户地址不在,则为新用户,加入列表
    if not clientAddress in userList:
        userList[clientAddress] = m
        SendUsers(userList, m + ' 已经加入群聊!')
    elif m == 'quit':#
        SendUsers(userList, userList[clientAddress]+' 已经离开群聊!')
        del userList[clientAddress]
    else:#聊天
        SendUsers(userList, userList[clientAddress]+':'+m )
  • 客户端

客户端为了保证收发同时,需要两个线程实现的。一个线程Receive() 负责接收并显示消息,另一个线程Send() 负责获取输入和发送消息。Python里threading库可以实现多线程编程。

UDPClient.py代码

from socket import *
import threading#多线程
import time

#发送函数线程
def Send(clientSocket, serverName, serverPort):
    while True:
        m = input()
        clientSocket.sendto(m.encode(), (serverName, serverPort))
        if m == 'quit':
            time.sleep(1)#延时1秒再关闭连接,避免收发线程冲突
            clientSocket.close()#发送退出则断开连接并跳出循环
            break

#接收函数线程
def Receive(clientSocket):
    while True:
        try:    # 利用 close 作为退出标志
            modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
            print(modifiedMessage.decode())
        except:
            break

serverName = 'localhost'
serverPort = 12000

clientSocket = socket(AF_INET, SOCK_DGRAM)#创建客户端进程套接字

#发送昵称给服务器
name = input('请输入昵称:') 
clientSocket.sendto(name.encode(), (serverName, serverPort))

print('欢迎', name, ',输入 <quit> 退出群聊!')

#创建接收进程并启动
th_Send = threading.Thread(target=Send, args=(clientSocket, serverName, serverPort))
th_Receive = threading.Thread(target=Receive, args=(clientSocket,))
th_Send.start()
th_Receive.start()
  • 运行效果

总体效果

【计算机网络】4 Socket网络编程

  • 开启服务器,jennie客户端和john客户端陆续加入群聊

服务器先开启,jennie客户端先发送昵称加入消息,服务器收到消息并将jennie加入用户字典并向jennie回复欢迎信息,并将新用户加入消息转发给全部用户(当前用户字典仅有jennie)。接下来john加入,同样的过程,这时全部用户(jennie,john)同时收到转发消息,后面还有Mike加入下图未展示(左:服务器,中:john客户端2,右:jennie客户端1)

【计算机网络】4 Socket网络编程

  • 聊天(4栏:服务器mikejohn,  jennie

    jennie先发送消息“你们知道那时候可以会深大吗”,服务器收到消息后通过查询用户字典知道jennie为老用户,发送的是一般聊天信息,则会加上jennie昵称把该消息转发给全部用户(用户字典里:jennie, john, mike),全部用户客户端可以收到该条消息。

【计算机网络】4 Socket网络编程

  • mike回复消息同样被转发给全部用户

【计算机网络】4 Socket网络编程

  • 用户退出

    用户在发送‘quit’给服务器后,服务器会将信息该用户退出信息转发给全部用户,而该用户也会等待1s后(避免与receive线程冲突)在关闭客户端连接。如图中mike退出。

【计算机网络】4 Socket网络编程

    mike退出后其他用户继续聊天,服务器也继续接收。

【计算机网络】4 Socket网络编程

问题及解决:

  • URL 请求程序

    • 在创建文件名名时可以直接通过接受的url字符串切片获得。
    • 可通过os库的相关功能获得文件大小
  • 系统时间查询

  • 在“系统时间查询”实验部分中,我发现要实现远程就必须添加服务器地址的输入。也必须获得本机IP。通过ipconfig查询,本机IP:192.168.0.107
  • 通过socket库的getsockname() 函数可获得本地进程IP地址和端口号,getpeername() 获得所连接的远程服务端的地址和端口号。
  • 利用time库获得格式化系统时间表达。
  • 网络文件传输

    • 通过文件分组的大小是否为0判断是否文件发送完毕。
    • 利用os库判断文件是否存在
  • 网络聊天室

    • 显示套接字不可以作为线程函数参数,经查阅资料发现线程参数接受的是元组,需要在参数参数后面加‘,’代表这是个元组。
    • 某一个用户退出时,服务器显示某个远程主机强制断开连接报错,而代码里我在用户发送‘quit’后就断开该客户端,可能会导致后续客户端继续收服务器信息的receive线程出现问题,所以为了避免冲突我在用户发送‘quit’后等待1s再关闭客户端连接,避免客户端receive线程发生冲突,问题也解决了。

实验心得体会

通过本次实验,学会通过python的requests库来完成url请求并获得网页文件和相关信息。同时可利用os库获取文件具体信息。

我加深关于TCP/UDP套接字的认识,了解了他们的区别,比如TCP套接字连接后服务端就可以保持监听状态,创建连接后的短期内通信与同一客户端无需再次连接。而UDP并无严格意义的连接过程,服务端也没有监听的概念。

另外我通过该次试验,初步学习了socket编程方法,通过套接字的创建实现服务端与客户端基于TCP/UDP协议的进程通信,实现文件传输。

学会了基于此再利用多线程编程的知识即可实现多人聊天功能,比如在这里通过利用python的threading库实现客户端的收发双线程并发通信。注意的是当客户端准备关闭连接的时候,需等待一段时间避免接收线程由于管道的提前关闭而导致出错。 

总结

我们可以通过python的requests库来完成url请求并获得网页文件和相关信息。

通过套接字的创建实现服务端与客户端基于TCP/UDP协议的进程通信,实现文件传输。

基于此再利用多线程编程的知识即可实现多人聊天功能,比如在这里通过利用python的threading库实现客户端的收发双线程并发通信。注意的是当客户端准备关闭连接的时候,需等待一段时间避免接收线程由于管道的提前关闭而导致出错。文章来源地址https://www.toymoban.com/news/detail-430039.html

到了这里,关于【计算机网络】4 Socket网络编程的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 【计算机网络】网络编程接口 Socket API 解读(4)

             Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。         本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。 poll()           遵

    2024年02月09日
    浏览(54)
  • 【计算机网络】网络编程接口 Socket API 解读(1)

             Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。         本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。 遵循 POSIX.1 - 2001、POS

    2024年02月09日
    浏览(41)
  • 【计算机网络】网络编程接口 Socket API 解读(6)

             Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。         本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。 recv()           遵

    2024年02月07日
    浏览(41)
  • 【计算机网络】网络编程接口 Socket API 解读(9)

             Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。         本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。 续  【计算机网络】网

    2024年02月08日
    浏览(46)
  • 【计算机网络】网络编程接口 Socket API 解读(2)

             Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。         本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。 遵循 POSIX.1 - 2008    

    2024年02月09日
    浏览(39)
  • 【计算机网络】网络编程接口 Socket API 解读(3)

             Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。         本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。 poll()           遵

    2024年02月09日
    浏览(46)
  • 【计算机网络】网络编程接口 Socket API 解读(5)

             Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。         本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。 connect()         

    2024年02月08日
    浏览(43)
  • 【计算机网络】网络编程接口 Socket API 解读(10)

             Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。         本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。         这个是 RFC 7

    2024年02月08日
    浏览(51)
  • 【计算机网络】网络编程接口 Socket API 解读(11)

             Socket 是网络协议栈暴露给编程人员的 API,相比复杂的计算机网络协议,API 对关键操作和配置数据进行了抽象,简化了程序编程。         本文讲述的 socket 内容源自 Linux man。本文主要对各 API 进行详细介绍,从而更好的理解 socket 编程。 遵循 POSIX.1-2008      

    2024年02月08日
    浏览(43)
  • 计算机网络技术与JAVA网络编程手写Socket聊天室-----JAVA入门基础教程-----计算机网络经典

    import java.io.*; import java.net.Socket; import java.util.Scanner; public class ChatClient { public static void main(String[] args) { try { Socket socket = new Socket(\\\"127.0.0.1\\\",9090); new Thread(new Runnable() { @Override public void run() { InputStream inputStream = null; while(true) { try { inputStream = socket.getInputStream(); } catch (IOException e)

    2024年02月15日
    浏览(57)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包