㈠ c#udp源端口目的端口不同
在unity中使用UDP进行数据的交互,建立C/S模式,两个客户端和一个服务端。两个客户端使用不同的端口往服务端发送数据,服务端根据收到的数据进行处理和判断,控制服务端的显示。
说明:两个客户端连接的是Kinect V2,需要将检测到的人体的数据信息发送到服务端进行系统数据的整体显示。指定的消息协议是ClientID|index|PosLeft|Left_S|PosRight|Right_S|ACTION| ClientID|index|PosLeft|Left_S|PosRight|Right_S|ACTION| ...
这是客户端根据检测到人体的数量向服务端发送的数据格式。
服务端:使用两个线程用于接收两个客户端的数据,将收到的数据添加到Queue中。在需要显示数据的Update中从Queue中取出数据进行处理控制。
这里服务端的接收数据脚本直接上代码:
using UnityEngine;
using System.Collections;
//引入库
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Collections.Generic;
public class UdpHelpHandler : MonoBehaviour {
//以下默认都是私有的成员
Socket socket,socket2; //目标socket
EndPoint clientEnd; //客户端
IPEndPoint ipEnd,ipEnd2; //侦听端口
string recvStr,recvStr2; //接收的字符串
string sendStr; //发送的字符串
byte[] recvData=new byte[1024]; //接收的数据,必须为字节
byte[] recvData2=new byte[1024]; //接收的数据,必须为字节
byte[] sendData=new byte[1024]; //发送的数据,必须为字节
int recvLen,recvLen2; //接收的数据长度
Thread connectThread,connectThread2; //连接线程
int[] WaveCounts = new int[2];
int[] TPoseCounts = new int[2];
public Queue<string> queueClient1 = new Queue<string>();
public Queue<string> queueClient2 = new Queue<string>();
private System.Object thisLock = new System.Object ();
//初始化
public void InitSocket()
{
//定义侦听端口,侦听任何IP
ipEnd=new IPEndPoint(IPAddress.Any,2000);
//定义套接字类型,在主线程中定义
socket=new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
//服务端需要绑定ip
try{
socket.Bind(ipEnd);
}
catch (System.Exception ex)
{
socket.Close ();
Debug.LogError(ex.Message + "\n" + ex.StackTrace);
}
//定义侦听端口,侦听任何IP
ipEnd2=new IPEndPoint(IPAddress.Any,3000);
//定义套接字类型,在主线程中定义
socket2=new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
//服务端需要绑定ip
try{
socket2.Bind(ipEnd2);
}
catch (System.Exception ex)
{
socket2.Close ();
Debug.LogError(ex.Message + "\n" + ex.StackTrace);
}
//定义客户端
IPEndPoint sender=new IPEndPoint(IPAddress.Any,0);
clientEnd=(EndPoint)sender;
print("waiting for UDP dgram");
//开启一个线程连接,必须的,否则主线程卡死
connectThread=new Thread(new ThreadStart(SocketReceive));
connectThread.Start();
//开启一个线程连接,必须的,否则主线程卡死
connectThread2=new Thread(new ThreadStart(SocketReceive2));
connectThread2.Start();
}
void SocketSend(string sendStr)
{
//清空发送缓存
sendData=new byte[1024];
//数据类型转换
sendData=Encoding.ASCII.GetBytes(sendStr);
//发送给指定客户端
socket.SendTo(sendData,sendData.Length,SocketFlags.None,clientEnd);
}
//服务器接收
void SocketReceive()
{
//进入接收循环
while(true)
{
//对data清零
recvData=new byte[1024];
//获取客户端,获取客户端数据,用引用给客户端赋值
recvLen=socket.ReceiveFrom(recvData,ref clientEnd);
//输出接收到的数据
recvStr=Encoding.ASCII.GetString(recvData,0,recvLen);
char[] msgDelim = { '|' };
string[] asMessages = recvStr.Split(msgDelim);
if (asMessages.Length > 7) {
queueClient1.Enqueue (recvStr);
if (int.Parse (asMessages [0]) == 2) {
if (int.Parse (asMessages [6]) == 6) { //wave
SetWaveCountsClient1 (2);
}
} else if (int.Parse (asMessages [0]) == 3) {
if (int.Parse (asMessages [6]) == 6) { //wave
SetWaveCountsClient2 (3);
}
}
}
}
}
//服务器接收
void SocketReceive2()
{
//进入接收循环
while(true)
{
//对data清零
recvData2=new byte[1024];
//获取客户端,获取客户端数据,用引用给客户端赋值
recvLen2=socket2.ReceiveFrom(recvData2,ref clientEnd);
//输出接收到的数据
recvStr2=Encoding.ASCII.GetString(recvData2,0,recvLen2);
char[] msgDelim = { '|' };
string[] asMessages = recvStr2.Split(msgDelim);
if (asMessages.Length > 7)
{
queueClient2.Enqueue (recvStr2);
if (int.Parse(asMessages[0]) == 2)
{
if(int.Parse(asMessages[6]) == 6) //wave
{
SetWaveCountsClient1(2);
}
}
else if (int.Parse(asMessages[0]) == 3)
{
if (int.Parse(asMessages[6]) == 6) //wave
{
SetWaveCountsClient2(3);
}
}
}
}
}
public void SetWaveCountsClient1(int index)
{
if (index == 2)
{
WaveCounts[0]++;
}
}
public void SetWaveCountsClient2(int index)
{
if (index == 3)
WaveCounts[1]++;
}
public void SetTposeCounts(int index)
{
if (index == 2)
TPoseCounts[0]++;
else if (index == 3)
TPoseCounts[1]++;
}
public int GetWaveCounts(int index)
{
int ret = 0;
if (index == 2)
{
if (WaveCounts[0] > 0)
ret = WaveCounts[0]--;
}
else if (index == 3)
{
if (WaveCounts[1] > 0)
ret = WaveCounts[1]--;
}
return ret;
}
public int GetTposeCounts(int index)
{
int ret = 0;
if (index == 2)
{
if (TPoseCounts[0] > 0)
ret = TPoseCounts[0]--;
}
else if (index == 3)
{
if (TPoseCounts[1] > 0)
ret = TPoseCounts[1]--;
}
return ret;
}
//返回接收到的字符串
public string GetRecvStr()
{
string returnStr="";
//加锁防止字符串被改
if (queueClient1.Count > 0)
{
lock (/*thisLock*/queueClient1) {
//returnStr=recvStr;
returnStr = queueClient1.Dequeue ();
}
}
return returnStr;
}
//返回接收到的字符串
public void setRecvStr()
{
//加锁防止字符串被改
lock(thisLock)
{
recvStr = null;
}
}
//返回接收到的字符串
public string GetRecvStr2()
{
string returnStr="";
if (queueClient2.Count > 0)
{
lock (/*thisLock*/queueClient2) {
//returnStr=recvStr;
returnStr = queueClient2.Dequeue ();
}
}
return returnStr;
}
//返回接收到的字符串
public void setRecvStr2()
{
//加锁防止字符串被改
lock(thisLock)
{
recvStr2 = null;
}
}
//连接关闭
public void SocketQuit()
{
//关闭线程
if(connectThread!=null)
{
connectThread.Interrupt();
connectThread.Abort();
}
if(connectThread2!=null)
{
connectThread2.Interrupt();
connectThread2.Abort();
}
//最后关闭socket
if(socket!=null)
socket.Close();
//最后关闭socket
if(socket2!=null)
socket2.Close();
print("disconnect");
}
}
客户端代码如下:
using UnityEngine;
using System.Collections;
//引入库
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;
using System.Xml;
//客户端
public class UdpHelpHandler : MonoBehaviour {
//以下默认都是私有的成员
Socket socket; //目标socket
EndPoint serverEnd; //服务端
IPEndPoint ipEnd; //服务端端口
string recvStr; //接收的字符串
string sendStr; //发送的字符串
byte[] recvData=new byte[1024]; //接收的数据,必须为字节
byte[] sendData=new byte[1024]; //发送的数据,必须为字节
int recvLen; //接收的数据长度
Thread connectThread; //连接线程
public bool isClient =true;
//初始化
public void InitSocket(string ipHostString,int port)
{
//定义连接的服务器ip和端口,可以是本机ip,局域网,互联网
ipEnd=new IPEndPoint(IPAddress.Parse(ipHostString),port);
//定义套接字类型,在主线程中定义
socket=new Socket(AddressFamily.InterNetwork,SocketType.Dgram,ProtocolType.Udp);
//定义服务端
IPEndPoint sender=new IPEndPoint(IPAddress.Any,0);
serverEnd=(EndPoint)sender;
print("waiting for sending UDP dgram....");
//建立初始连接,这句非常重要,第一次连接初始化了serverEnd后面才能收到消息
//开启一个线程连接,必须的,否则主线程卡死
connectThread=new Thread(new ThreadStart(SocketReceive));
connectThread.Start();
}
public void SocketSend(string sendStr)
{
//清空发送缓存
sendData=new byte[1024];
//数据类型转换
sendData=Encoding.ASCII.GetBytes(sendStr);
//发送给指定服务端
socket.SendTo(sendData,sendData.Length,SocketFlags.None,ipEnd);
}
//服务器接收
void SocketReceive()
{
//进入接收循环
while(true)
{
// print("recv thread");
//对data清零
recvData=new byte[1024];
//获取客户端,获取服务端端数据,用引用给服务端赋值,实际上服务端已经定义好并不需要赋值
recvLen=socket.ReceiveFrom(recvData,ref serverEnd);
// print("message from: "+serverEnd.ToString()); //打印服务端信息
//输出接收到的数据
recvStr=Encoding.ASCII.GetString(recvData,0,recvLen);
// print(recvStr);
}
}
//连接关闭
public void SocketQuit()
{
//关闭线程
if(connectThread!=null)
{
connectThread.Interrupt();
connectThread.Abort();
}
//最后关闭socket
if(socket!=null)
socket.Close();
}
}
文章知识点与官方知识档案匹配
网络技能树首页概览
21577 人正在系统学习中
点击阅读全文
打开CSDN,阅读体验更佳
QT多线程,使用串口接收数据通过UDP端口进行数据转发_是小峰呀的博客-CS...
ui(newUi::Widget){ui->setupUi(this);socket=newQUdpSocket();localThread=newmyThread();timer=newQTimer();socket->bind(3080);//删除注释后,是由按钮控制数据发送,此时需要将带定时器的connet注释。
UDP数据通信,使用一个DatagramSocket实现向多个地址发送数据和接收各个...
往不同的服务器发送数据,只需要启动多个线程,调用上面的方法,替换地址和端口即可 //connect方法的意思是将socket与指定地址绑定,绑定成功后只能往该地址发送数据。并不是建立连接,因为udp是面向非连接的 mSocket.connect(address, hostPort...
c#向指定端口发送数据,监听指定端口
c#向指定端口发送数据,监听指定端口,使用端口监听获取数据信息,向指定端口发送需要的数据
最新发布 C# UDP发送和接收数据类
C# UDP发送和接收数据类
继续访问
UDP端口传递接收数据_wei395107171的博客
UDP端口传递接收数据 package com.udp.test; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import java.net.DatagramPacket; import java.net.DatagramSocket;...
...解决端口复用的问题)_酷侠一剑绝ggh的博客_udp端口复用
UDP组播通信(解决端口复用的问题) 最近在写一个组播通信的功能,结果发现接受同一台电脑上只能运行一个接收端,如果运行两个时,第二个运行的程序不能收到数据。查找原因是因为没有设置端口数据复用的功能(setsockpot),setsockpot的调用...
NIO之UDP监听多个端口获取请求信息
最近需要继承一个udp服务,需求是这样的,服务端接收消息,并且支持多个udp端口。 例如: 客户端:port 11112 port 11113 port 11114 服务端:要可以同时监听这三个端口,接收发送的报文。 Select监听端口,然后获取请求数据 附代码 @Override public void run(String... args) throws Exception {...
继续访问
UDP客户端实现在不同端口上发送和接收数据
普通udp通信,客户端在发送完数据后,只需要在相同socket上,recvfrom即可 服务端给的回应,可以是同一端口,也可以是不同端口,客户端在接收时,需要指点一个本地端口进行接收,此端口也可以用bind和创建的socket绑定。 但是bind必须是在通过这个socket发送数据前绑定,在发送数据后再bind会失败。 下面给出代码: #define SEND_PORT 8000
继续访问
发送方 获取 绑定 端口 linux c,多播报文的发送和接收
1实验目的掌握多播的原理及如何进行多播报文的发送和接受2注意事项需包括ws2tcpip.h文件发送者和所有接受者在同一网内不考虑TTL值,回环状态通过setsockopt( )函数设置选项来实现多播数据的发送和接收3试验流程3.1多播数据发送端流程l创建一个数据报套接口l设置多播地址(例:239.192.1.2)和端口号(例:12345)l调用setsockopt( )函数设置发送的数据报本地接口...
继续访问
网络编程之 Udp接收数据
udp接收数据,网络调试助手担任发送方,但发送时需要对方的也就是虚拟机的ip 和端口,ip可以通过config获取,那么如何让一个程序拥有一个固定端口呢? 创建套接字的时候是没有端口号的,好比买了手机没有手机号,别...
继续访问
C语言实现UDP服务器,客户端
服务器 #include<stdio.h> #include "unistd.h" #include "sys/socket.h" #include "netinet/in.h" #include "arpa/inet.h" #include "string.h" #include "stdlib.h" #define IP "127.0.0.1" #define PORT 8888 int main() { int fb=0,len=0; char buf[512]=
继续访问
c udp服务器端一对多持续接收消息,C - 使用select在多个端口上侦听的简单ipv6 udp服务器。从一个端口接收消息,而不是另一个...
#include #include #include #include #include int max(int socket_handle[]);int main(void){int max_clients_allowed = 2;int socket_handle[max_clients_allowed];int client_handle[max_clients_allowed];st...
继续访问
C# 简单的UDP服务器,实现异步接收UDP消息
C# 异步接收UDP消息 源代码 主要方法 async Task ListenForUdp(int port, Action<UdpReceiveResult> receivedHandle) { using (var udpClient = new UdpClient(port)) { while (true) { try { receivedHandle(await
继续访问
UDP数据通信,使用一个DatagramSocket实现向多个地址发送数据和接收各个地址的数据返回
有时候需要一个客户端向多个地址发送数据并接收返回的需求 1、创建DatagramSocket DatagramSocket 有多个构造方法 DatagramSocket():创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、本机所有可用端口中随机选择的某个端口。 DatagramSocket(int prot):创建一个DatagramSocket实例,并将该对象绑定到本机默认IP地址、指定端口。 DatagramSocket(int port, InetAddre.
继续访问
python知识点——TCP和UDP的区别
相同点 UDP协议和TCP协议都是传输层协议。 TCP(Transmission Control Protocol,传输控制协议)提供的是面向连接,可靠的字节流服务。即客户和服务器交换数据前,必须现在双方之间建立一个TCP连接,之后才能传输数据。并且提供超时重发,丢弃重复数据,检验数据,流量控制等功能,保证数据能从一端传到另一端。 UDP(User Data Protocol,用户数据报协议)是一个简单的面向数据报的运输层协议。它不提供可靠性,只是把应用程序传给IP层的数据报发送出去,但是不能保证它们能到达
继续访问
UDP多线程同时建立多个通信端口
1.需要注意的是:::bind(serSocket, (sockaddr*)&serAddr, sizeof(serAddr)) == SOCKET_ERROR) ,bind()函数前必须添加::,否则,在使用thread头文件后,使用了using namespace std的情况下,会被默认成std::bind,导致编译失败 (1)server #include<WinS...
继续访问
C#winform UDP通信 发送和接收信息
using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Drawing; using System.Linq; using System.Net; using System.Net.Sockets; using System.Text;
继续访问
udp多线程 java_多线程以从多个UDP客户端接收数据
我想从不同的客户端接收数据(客户端数量是固定的,比如10),并且每个客户端在5个不同的预定义端口上发送数据,这些端口不会改变 . (例如,客户端1端口5000,5001,5002等) . 所有客户端都可以同时发送数据 . (以上都是固定的)在TCP中说,我可以为我们接受的每个连接创建多个线程,如下所示 . UDP is connectionless,So how can we create ...
继续访问
不同端口间的信息交换-使用udp协议
本文主要内容: 1.套接字(socket)简介; 2.udp简介; 3.udp发送数据及接收数据; 4.模拟qq聊天。 1.套接字(socket)简介 本地可以通过进程PID来唯一标识一个进程,但在网络中这是行不通的。ip地址可以唯一标识网络中的主机,传输层的“协议+端口号”可以唯一标识主机...
继续访问
c语言udp监听多个端口号,多个UDP监听同一个端口
测试结果:客户端的数据总是发给最后一个打开的服务器服务器代码:socket()->setsockopt()->bind()->recvfrom()/sendto()1 #include 2 #include 3 #include 4 #include 5 #include 6 #include 7 #include 8 #include 91011 int main(int ar...
继续访问
udp接收多个端口的数据
㈡ python后端开发需要学什么
第一阶段:Python语言基础
主要学习Python最基础知识,如Python3、数据类型、字符串、函数、类、文件操作等。阶段课程结束后,学员需要完成Pygame实战飞机大战、2048等项目。
第二阶段:Python语言高级
主要学习Python库、正则表达式、进程线程、爬虫、遍历以及MySQL数据库。
第三阶段:Pythonweb开发
主要学习HTML、CSS、JavaScript、jQuery等前端知识,掌握python三大后端框架(Django、 Flask以及Tornado)。需要完成网页界面设计实战;能独立开发网站。
第四阶段:Linux基础
主要学习Linux相关的各种命令,如文件处理命令、压缩解压命令、权限管理以及Linux Shell开发等。
第五阶段:Linux运维自动化开发
主要学习Python开发Linux运维、Linux运维报警工具开发、Linux运维报警安全审计开发、Linux业务质量报表工具开发、Kali安全检测工具检测以及Kali 密码破解实战。
第六阶段:Python爬虫
主要学习python爬虫技术,掌握多线程爬虫技术,分布式爬虫技术。
第七阶段:Python数据分析和大数据
主要学习numpy数据处理、pandas数据分析、matplotlib数据可视化、scipy数据统计分析以及python 金融数据分析;Hadoop HDFS、python Hadoop MapRece、python Spark core、python Spark SQL以及python Spark MLlib。
第八阶段:Python机器学习
主要学习KNN算法、线性回归、逻辑斯蒂回归算法、决策树算法、朴素贝叶斯算法、支持向量机以及聚类k-means算法。
关于python后端开发需要学什么的内容,青藤小编就和您分享到这里了。如果您对python编程有浓厚的兴趣,希望这篇文章可以为您提供帮助。如果您还想了解更多关于python编程的技巧及素材等内容,可以点击本站的其他文章进行学习。
㈢ 软件测试面试题:WEB+网络|接口测试|性能测试|自动化测试
1. http代码表,常考题目
404:找不到资源
500:服务器内部错误,无法完成请求。
501:服务器不支持请求的功能,无法完成请求。
502:充当网关或代理的服务器,从远端服务器接收到了一个无效的请求。
301:永久移动。请求的资源已被永久的移动到新URI,返回信息会包括新的URI,浏览器会自动定向到新URI,今后任何新的请求都应使用新的URI代替。
302:临时移动。与301类似。但资源只是临时被移动,客户端应继续使用原有URI。
200:成功。
2. TCP/IP四层网络模型
链路层、网络层、传输层、应用层。
3. TCP/UDP区别?
TCP: 可靠传输协议,需要三次握手连接,有确认重传机制,特点是可靠、准确、有拥塞控制,缺点就是比较慢,传输量比较小,适用于升级、下载;一句话:TCP是可靠的传输。
UDP: 不可靠传输协议,面向非连接的协议,优点是传输量大、速度快,缺点是已丢失、没有拥塞控制,适用于直播、视频等。一句话:UDP是不可靠的传输。
4. html css js运行的先后顺序是什么?
界面加载的时候先加载html在加载css最后加载js
5. session和cookie的区别是什么
1. session存放在服务器端用来校验客户端的身份
2. cookie存放在客户端,每次从客户端往服务器发请求时,将cookie带到服务器端,用来校验客户端的身份
1. 怎么用JMeter测试接口?
如果使用JMeter进行接口测试:
1) 测试前了解需求,根据接口规格说明书梳理业务;
2) 接下来设计用例,分析接口的入参和出参,分清楚有哪些有效输入和无效输入,设计用例(原则:用最少的用例覆盖所有有效输入,针对每一个无效的输入设计一个测试用例,如果有错误码没有覆盖到,还要对每个未覆盖的错误码分别设计一个用例);
3) 准备测试数据,比如:测试所需的账号、密码、key 等信息;
4) 打开JMeter,创建一个线程组,根据接口类型,填写好对应的接口地址和请求方式等;
5) 参数化配置,添加配置元件CSV Data Set Config,定义变量,并准备CSV格式的数据,变量的引用用${变量名}的格式;
6) 添加断言来判断测试结果的正确性,用得最多的是响应断言;
7) 添加监听器,比如查看结果树,对测试结果进行监听;
8) 运行测试用例;
9) 查看监听器结果,来判断用例的执行是成功还是失败,针对失败的用例,分析其失败原因;
10) 针对测试中发现的问题,给开发提单,直到问题最终解决。
11) 最后输出测试报告。
2. 怎么用Postman测试接口?
如果使用Postman测试接口:
其中1,2,3点相同,工具使用方面则比JMeter跟简单,工具的主要的步骤是添加对应的请求、填写主机URL及入参、添加测试套、运行测试套、分析结果出报告。
3. 在JMeter上如何把上一个请求的结果作为下一个请求的参数?
使用正则表达式提取器提取上一个请求的响应中的信息,保存一个引用名称比如abc,在下一个请求的参数中,用${abc}的格式来引用提取的结果。
常用的正则表达式格式:(.+?),其中.表示匹配任意字符串,+表示只匹配一次,?表示匹配到就停下来。
一般是我们功能测试完成最后两三天时间测试性能。
1、先是分析需求计算出并发数,TPS,响应时间和 CPU,内存,硬盘和网络IO这些指标。
2、制定测试方案,主要包括环境,计划和具体测试那些场景(如可靠性,并发,负载,压力测试等)
3、根据场景用Badboy录制脚本,导出为JMeter工具支持的脚本。
4、用JMeter工具打开脚本,进行脚本调试,加一些断言,监听器,参数化等。
5、接下来执行性能测试,然后主要收集监听器和收集服务器CPU,内存,硬盘和网络IO等分析是否满足需求,如果满足就输出性能测试报告。
6、如果指标不能满足,反馈给开发进行调优。调优后继续测试,一直到满足需求后最终输出测试报告。
1. Python怎么定义一个函数?
你可以定义一个由自己想要功能的函数,以下是简单的规则:
1) 函数代码块以def关键词开头,后接函数标识符名称和圆括号()。
2) 任何传入参数和自变量必须放在圆括号中间。圆括号之间可以用于定义参数。
3) 函数的第一行语句可以选择性地使用文档字符串—用于存放函数说明。
4) 函数内容以冒号起始,并且缩进
5) return[表达式]结束函数,选择性地返回一个值给调用方。不带表达式的return相当于返回None
2 Python切片
3. Python上用过什么库/模块?
webdriver:定位和操作元素
time:设置等待时间
ActionChains:动作链,完成鼠标的相关操作
Keys:键盘的相关操作
WebDriverWait:设置显式等待
Expect_Conditions:针对单个元素,设置显式等待的场景
PIL:截图
Select:下拉选择框的操作
unittest python:自带的单元测试框架
HTMLTestRunner:运行脚本,生成报告
ddt:实现数据驱动测试,行为和数据分离
4. 你做过自动化测试吗?
我在上一份工作中,公司去年下半年也开始规划做Web 自动化,采用Python作为开发语言,通过Selenium WebDriver定位和操作页面元素,自动化框架用的是unittest。我主要负责写测试脚本。
假设一个测试团队有5个人:1资深(测试经理)+2~3个中级(自动化+手动)+1 个初级(手动)
5. 使用什么工具进行的自动化测试
使用的工具是Selenium(Web自动化工具)
6. 用的什么编程语言
用的Python
7. Selenium 用的是哪个版本的的?Python用的是哪个版本的?
用的是selenium 3.11.0和Python2.7.10
8. Selenium的工作原理?
1)对html元素定位
2)模拟对第一步定位到的元素进行点击、输入、选择等操作一句话:定位元素,操作元素。
9. 元素定位方法有哪些?
要点:8种定位方法
1) 根据元素的属性值定位,比如 id、name、class、标签名、链接文字和部分链接文字;
2) 根据CSS选择器定位;
3) 根据 XPath 定位;
10. 子页面里的元素怎么定位?
先切换到框架里,然后再定位,用switch_to_frame函数根据子页面id或name,切换到子页面;定位完了如果要再定位主页面的元素,要用switch_to_default_content 函数先返回主页面。
11. 怎么定位alert弹窗?或者这样问:怎么处理JS原生窗口?
要点:主要涉及点击弹窗确认按钮、强行关闭弹窗、获取弹窗中的文字等操作。
1) 点击弹窗的确定按钮,用如下函数:
driver.switch_to_alert().accept()
2) 强行关闭,点击右上角的叉叉,用如下函数:
driver.switch_to_alert().dismiss()
3) 获取弹窗里的文字,用如下函数:
driver.switch_to_alert().text
12. 怎么运行自动化用例并生成测试报告?
以unittest为例,我通常的做法是把用例加载到测试套中,做成一个脚本,在命令窗口下运行脚本,报告的生成用第三方模块HTML TestRunner来生成。
13. 怎么定位/操作图片中的验证码?
用tesseract OCR引擎处理图片中的验证码,步骤:
(1)对整个屏幕截屏,保存成png格式的图片;
(2)在截取的图片中定位验证码图片的位置坐标;
(3)根据坐标对验证码截图;
(4)在图片中提取验证码,输入到输入框。
㈣ python udp多线程的问题
for out_port in self.output_port:
soc = socket.socket(socket.AF_INET,socket.SOCK_DGRAM)
soc.connect(("localhost",out_port))
_output.append(soc)
不要用output_port,用input_port。
你这里是往input_port发送数据,不需要关心自己的port,而是对端的port
㈤ 在Linux 上,编写一个每秒接收 100万UDP数据包的程序究竟有多难
首先,我们假设:
测量每秒的数据包(pps)比测量每秒字节数(Bps)更有意思。您可以通过更好的管道输送以及发送更长数据包来获取更高的Bps。而相比之下,提高pps要困难得多。
因为我们对pps感兴趣,我们的实验将使用较短的 UDP 消息。准确来说是 32 字节的 UDP 负载,这相当于以太网层的 74 字节。
在实验中,我们将使用两个物理服务器:“接收器”和“发送器”。
它们都有两个六核2 GHz的 Xeon处理器。每个服务器都启用了 24 个处理器的超线程(HT),有 Solarflare 的 10G 多队列网卡,有 11 个接收队列配置。稍后将详细介绍。
测试程序的源代码分别是:udpsender、udpreceiver。
预备知识
我们使用4321作为UDP数据包的端口,在开始之前,我们必须确保传输不会被iptables干扰:
Shell
receiver$ iptables -I INPUT 1 -p udp --dport 4321 -j ACCEPT
receiver$ iptables -t raw -I PREROUTING 1 -p udp --dport 4321 -j NOTRACK
为了后面测试方便,我们显式地定义IP地址:
Shell
receiver$ for i in `seq 1 20`; do
ip addr add 192.168.254.$i/24 dev eth2;
done
sender$ ip addr add 192.168.254.30/24 dev eth3
1. 简单的方法
开始我们做一些最简单的试验。通过简单地发送和接收,有多少包将会被传送?
模拟发送者的伪代码:
Python
fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
fd.bind(("0.0.0.0", 65400)) # select source port to rece nondeterminism
fd.connect(("192.168.254.1", 4321))
while True:
fd.sendmmsg(["x00" * 32] * 1024)
因为我们使用了常见的系统调用的send,所以效率不会很高。上下文切换到内核代价很高所以最好避免它。幸运地是,最近Linux加入了一个方便的系统调用叫sendmmsg。它允许我们在一次调用时,发送很多的数据包。那我们就一次发1024个数据包。
模拟接受者的伪代码:
Python
fd = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
fd.bind(("0.0.0.0", 4321))
while True:
packets = [None] * 1024
fd.recvmmsg(packets, MSG_WAITFORONE)
同样地,recvmmsg 也是相对于常见的 recv 更有效的一版系统调用。
让我们试试吧:
Shell
sender$ ./udpsender 192.168.254.1:4321
receiver$ ./udpreceiver1 0.0.0.0:4321
0.352M pps 10.730MiB / 90.010Mb
0.284M pps 8.655MiB / 72.603Mb
0.262M pps 7.991MiB / 67.033Mb
0.199M pps 6.081MiB / 51.013Mb
0.195M pps 5.956MiB / 49.966Mb
0.199M pps 6.060MiB / 50.836Mb
0.200M pps 6.097MiB / 51.147Mb
0.197M pps 6.021MiB / 50.509Mb
测试发现,运用最简单的方式可以实现 197k – 350k pps。看起来还不错嘛,但不幸的是,很不稳定啊,这是因为内核在核之间交换我们的程序,那我们把进程附在 CPU 上将会有所帮助
Shell
sender$ taskset -c 1 ./udpsender 192.168.254.1:4321
receiver$ taskset -c 1 ./udpreceiver1 0.0.0.0:4321
0.362M pps 11.058MiB / 92.760Mb
0.374M pps 11.411MiB / 95.723Mb
0.369M pps 11.252MiB / 94.389Mb
0.370M pps 11.289MiB / 94.696Mb
0.365M pps 11.152MiB / 93.552Mb
0.360M pps 10.971MiB / 92.033Mb
现在内核调度器将进程运行在特定的CPU上,这提高了处理器缓存,使数据更加一致,这就是我们想要的啊!
2. 发送更多的数据包
虽然 370k pps 对于简单的程序来说已经很不错了,但是离我们 1Mpps 的目标还有些距离。为了接收更多,首先我们必须发送更多的包。那我们用独立的两个线程发送,如何呢:
Shell
sender$ taskset -c 1,2 ./udpsender
192.168.254.1:4321 192.168.254.1:4321
receiver$ taskset -c 1 ./udpreceiver1 0.0.0.0:4321
0.349M pps 10.651MiB / 89.343Mb
0.354M pps 10.815MiB / 90.724Mb
0.354M pps 10.806MiB / 90.646Mb
0.354M pps 10.811MiB / 90.690Mb
接收一端的数据没有增加,ethtool –S 命令将显示数据包实际上都去哪儿了:
Shell
receiver$ watch 'sudo ethtool -S eth2 |grep rx'
rx_nodesc_drop_cnt: 451.3k/s
rx-0.rx_packets: 8.0/s
rx-1.rx_packets: 0.0/s
rx-2.rx_packets: 0.0/s
rx-3.rx_packets: 0.5/s
rx-4.rx_packets: 355.2k/s
rx-5.rx_packets: 0.0/s
rx-6.rx_packets: 0.0/s
rx-7.rx_packets: 0.5/s
rx-8.rx_packets: 0.0/s
rx-9.rx_packets: 0.0/s
rx-10.rx_packets: 0.0/s
通过这些统计,NIC 显示 4 号 RX 队列已经成功地传输大约 350Kpps。rx_nodesc_drop_cnt 是 Solarflare 特有的计数器,表明NIC发送到内核未能实现发送 450kpps。
有时候,这些数据包没有被发送的原因不是很清晰,然而在我们这种情境下却很清楚:4号RX队列发送数据包到4号CPU,然而4号CPU已经忙不过来了,因为它最忙也只能读350kpps。在htop中显示为:
多队列 NIC 速成课程
从历史上看,网卡拥有单个RX队列,用于硬件和内核之间传递数据包。这样的设计有一个明显的限制,就是不可能比单个CPU处理更多的数据包。
为了利用多核系统,NIC开始支持多个RX队列。这种设计很简单:每个RX队列被附到分开的CPU上,因此,把包送到所有的RX队列网卡可以利用所有的CPU。但是又产生了另一个问题:对于一个数据包,NIC怎么决定把它发送到哪一个RX队列?
用 Round-robin 的方式来平衡是不能接受的,因为这有可能导致单个连接中数据包的重排序。另一种方法是使用数据包的hash值来决定RX号码。Hash值通常由一个元组(源IP,目标IP,源port,目标port)计算而来。这确保了从一个流产生的包将最终在完全相同的RX队列,并且不可能在一个流中重排包。
在我们的例子中,hash值可能是这样的:
Shell
1
RX_queue_number = hash('192.168.254.30', '192.168.254.1', 65400, 4321) % number_of_queues
多队列 hash 算法
Hash算法通过ethtool配置,设置如下:
Shell
receiver$ ethtool -n eth2 rx-flow-hash udp4
UDP over IPV4 flows use these fields for computing Hash flow key:
IP SA
IP DA
对于IPv4 UDP数据包,NIC将hash(源 IP,目标 IP)地址。即
Shell
1
RX_queue_number = hash('192.168.254.30', '192.168.254.1') % number_of_queues
这是相当有限的,因为它忽略了端口号。很多NIC允许自定义hash。再一次,使用ethtool我们可以选择元组(源 IP、目标 IP、源port、目标port)生成hash值。
Shell
receiver$ ethtool -N eth2 rx-flow-hash udp4 sdfn
Cannot change RX network flow hashing options: Operation not supported
不幸地是,我们的NIC不支持自定义,我们只能选用(源 IP、目的 IP) 生成hash。
NUMA性能报告
到目前为止,我们所有的数据包都流向一个RX队列,并且一个CPU。我们可以借这个机会为基准来衡量不同CPU的性能。在我们设置为接收方的主机上有两个单独的处理器,每一个都是一个不同的NUMA节点。
在我们设置中,可以将单线程接收者依附到四个CPU中的一个,四个选项如下:
另一个CPU上运行接收器,但将相同的NUMA节点作为RX队列。性能如上面我们看到的,大约是360 kpps。
将运行接收器的同一 CPU 作为RX队列,我们可以得到大约430 kpps。但这样也会有很高的不稳定性,如果NIC被数据包所淹没,性能将下降到零。
当接收器运行在HT对应的处理RX队列的CPU之上,性能是通常的一半,大约在200kpps左右。
接收器在一个不同的NUMA节点而不是RX队列的CPU上,性能大约是330 kpps。但是数字会不太一致。
虽然运行在一个不同的NUMA节点上有10%的代价,听起来可能不算太坏,但随着规模的变大,问题只会变得更糟。在一些测试中,每个核只能发出250 kpps,在所有跨NUMA测试中,这种不稳定是很糟糕。跨NUMA节点的性能损失,在更高的吞吐量上更明显。在一次测试时,发现在一个坏掉的NUMA节点上运行接收器,性能下降有4倍。
3.多接收IP
因为我们NIC上hash算法的限制,通过RX队列分配数据包的唯一方法是利用多个IP地址。下面是如何将数据包发到不同的目的IP:
1
sender$ taskset -c 1,2 ./udpsender 192.168.254.1:4321 192.168.254.2:4321
ethtool 证实了数据包流向了不同的 RX 队列:
Shell
receiver$ watch 'sudo ethtool -S eth2 |grep rx'
rx-0.rx_packets: 8.0/s
rx-1.rx_packets: 0.0/s
rx-2.rx_packets: 0.0/s
rx-3.rx_packets: 355.2k/s
rx-4.rx_packets: 0.5/s
rx-5.rx_packets: 297.0k/s
rx-6.rx_packets: 0.0/s
rx-7.rx_packets: 0.5/s
rx-8.rx_packets: 0.0/s
rx-9.rx_packets: 0.0/s
rx-10.rx_packets: 0.0/s
接收部分:
Shell
receiver$ taskset -c 1 ./udpreceiver1 0.0.0.0:4321
0.609M pps 18.599MiB / 156.019Mb
0.657M pps 20.039MiB / 168.102Mb
0.649M pps 19.803MiB / 166.120Mb
万岁!有两个核忙于处理RX队列,第三运行应用程序时,可以达到大约650 kpps !
我们可以通过发送数据到三或四个RX队列来增加这个数值,但是很快这个应用就会有另一个瓶颈。这一次rx_nodesc_drop_cnt没有增加,但是netstat接收到了如下错误:
Shell
receiver$ watch 'netstat -s --udp'
Udp:
437.0k/s packets received
0.0/s packets to unknown port received.
386.9k/s packet receive errors
0.0/s packets sent
RcvbufErrors: 123.8k/s
SndbufErrors: 0
InCsumErrors: 0
这意味着虽然NIC能够将数据包发送到内核,但是内核不能将数据包发给应用程序。在我们的case中,只能提供440 kpps,其余的390 kpps + 123 kpps的下降是由于应用程序接收它们不够快。
4.多线程接收
我们需要扩展接收者应用程序。最简单的方式是利用多线程接收,但是不管用:
Shell
sender$ taskset -c 1,2 ./udpsender 192.168.254.1:4321 192.168.254.2:4321
receiver$ taskset -c 1,2 ./udpreceiver1 0.0.0.0:4321 2
0.495M pps 15.108MiB / 126.733Mb
0.480M pps 14.636MiB / 122.775Mb
0.461M pps 14.071MiB / 118.038Mb
0.486M pps 14.820MiB / 124.322Mb
接收性能较于单个线程下降了,这是由UDP接收缓冲区那边的锁竞争导致的。由于两个线程使用相同的套接字描述符,它们花费过多的时间在UDP接收缓冲区的锁竞争。这篇论文详细描述了这一问题。
看来使用多线程从一个描述符接收,并不是最优方案。
5. SO_REUSEPORT
幸运地是,最近有一个解决方案添加到 Linux 了 —— SO_REUSEPORT 标志位(flag)。当这个标志位设置在一个套接字描述符上时,Linux将允许许多进程绑定到相同的端口,事实上,任何数量的进程将允许绑定上去,负载也会均衡分布。
有了SO_REUSEPORT,每一个进程都有一个独立的socket描述符。因此每一个都会拥有一个专用的UDP接收缓冲区。这样就避免了以前遇到的竞争问题:
Shell
1
2
3
4
receiver$ taskset -c 1,2,3,4 ./udpreceiver1 0.0.0.0:4321 4 1
1.114M pps 34.007MiB / 285.271Mb
1.147M pps 34.990MiB / 293.518Mb
1.126M pps 34.374MiB / 288.354Mb
现在更加喜欢了,吞吐量很不错嘛!
更多的调查显示还有进一步改进的空间。即使我们开始4个接收线程,负载也会不均匀地分布:
两个进程接收了所有的工作,而另外两个根本没有数据包。这是因为hash冲突,但是这次是在SO_REUSEPORT层。
结束语
我做了一些进一步的测试,完全一致的RX队列,接收线程在单个NUMA节点可以达到1.4Mpps。在不同的NUMA节点上运行接收者会导致这个数字做多下降到1Mpps。
总之,如果你想要一个完美的性能,你需要做下面这些:
确保流量均匀分布在许多RX队列和SO_REUSEPORT进程上。在实践中,只要有大量的连接(或流动),负载通常是分布式的。
需要有足够的CPU容量去从内核上获取数据包。
To make the things harder, both RX queues and receiver processes should be on a single NUMA node.
为了使事情更加稳定,RX队列和接收进程都应该在单个NUMA节点上。
虽然我们已经表明,在一台Linux机器上接收1Mpps在技术上是可行的,但是应用程序将不会对收到的数据包做任何实际处理——甚至连看都不看内容的流量。别太指望这样的性能,因为对于任何实际应用并没有太大用处。
㈥ 女孩子可以学习网络编程吗
可以,喜欢什么就学。至少学了才不会后悔当初为啥没选择。喜欢什么就去努力,像有女生喜欢打球,她们今年在奥运会上奉献了她们的力量,为国争优,值得骄傲。勇敢做自己喜欢的事情 ,学会了一样的发光发热,无论是在生活中,工作中还是哪里,付出就有回报。还有中国女生学飞机,她现在努力奋斗成了机长,也很厉害。她就是王峥。喜欢就去学,加油^0^~的也是女孩子,在这学起编程来,一点都不输给同龄的男孩子,所以不要认为学习编程是男孩子的专利呀。
其实编程主要是对孩子思维的培养,让孩子养成主动学习、主动思考、主动创造的好习惯。因为很多女孩子的逻辑思维能力也很强,也很喜欢思考,所以女孩子完全可以学习网络编程,编程有一个更好的优点,就是没有太多的勾心斗角。编程的就业前景非常不错的,所以不管是男孩还是女孩学好编程都很重要,相信不久的将来编程就和现在的办公软件一样是每个上班的人都要具备的技能。女孩子学起来也很快的,主要是现在的编程技术越来越普及了。女孩子当然可以学习网络编程,网络编程能够让你的思维变得更加紧密,逻辑更加清晰,也能够让你养成一个良好的学习,思考的习惯
㈦ 初学电脑编程需要什么
初学电脑编程需要学习英语,选择一门编程语言,要有数学基础,具体介绍如下:
1、英语基础
计算机英语与传统的英语知识不同,需要了解的大部分是计算机的专业单词或者词汇,普遍较为简单。但是在高级编程中,会出现比较生涩的词汇,对于想要参与计算机语言设计以及在职业发展上有更多追求的同学可以自学一下大学英语。
2、选择一门编程语言
选择一门编程语言。虽然目前编程语言有600种左右,但是比较流行的编程语言只有几十种,所以尽量选择流行程度比较高的编程语言来入门编程。对于没有明确编程场景的初学者来说,尽量选择全场景编程语言,比如Java、Python、C#等就是不错的选择
3、数学基础
当然拥有初中阶段的数学基础也可以成为一名合格的程序员,这也是目前很多计算机编程培训学校招收初中毕业学生的原因。但想要成为一名优秀的程序员,最少要高中及以上的数学基础,而且要懂得如何举一反三,灵活运用。
4、了解计算机操作系统原理
所有的开发或者说软件应用都是在特定的操作系统上进行的,所以计算机操作系统原理可以说是基础中的基础是必须要了解的。
5、数据结构和算法
这门课程能够决定一个人程序设计水平的高低,是学习过程中需要重点掌握的。C和C++都是可以选择的,前期可以先学C,再学C++会相对简单一些。
在学习编程语言的过程中,也需要同时学习计算机网络、数据库等相关知识,在当前的云计算和大数据时代背景下,还需要掌握如何通过云计算(PaaS)来辅助开发,以及如何利用大数据平台的各种资源。
㈧ 如何学习网络编程
具体到编程,用java来实现网络编程是很容易的,可以作为网络编程的入门。使用C++和winsock相对复杂一些。
总之看实际需要了。
你好初学网络编程者可以从以下几个步骤开展:
1)下载一个可以互动的学习工具,通过这个与这个工具互动,我们可以及时的学到每个api的结果如果。
对于有c/c++或java基础的朋友通过一两个礼拜的时间就可以上手了,另外个人建议初学者可以学习dive into python。
2)掌握网络编程中会用到的几个基本概念和内涵,比如IP地址,port号,socket等
3)记住和消化网络编程C/S模型,把server和client端编程的常用模式理解和消化
4)花几天时间学习socket api集,api集可以分为下面几大类:创建 socket bind listen accept收发 read/recv/recvfrom write/send/sendto关闭 close shutdown参数 getsockopt/setsockopt地址 gethostbyaddr getaddrbyhost,...在学习这些api时候,可以先关注在函数功能,参数意义上
5)结合python互动平台,实践socket api的用法,比如socket函数怎么使用,bind怎么使用等等。在互动过程中,我们可以变换参数,看看调用结果如何。比如,创建一个tcp socket的语法如下:socket(AF_INET,SOCK_STREAM)创建一个udp socket的语法如下:socket(AF_INET,SOCK_DGRAM)
6)学习socket server端编程实现简单规约比如echo,time等,然后通过cmd中的telnet来测试。
7)学习I/O模型,比如阻塞、非阻塞和反应式(select,poll,WaitForMultipleObject)等
8)学习Richard Stevens的《Unix网络编程》,深入学习其中的api原理以及服务端设计原理,并通过代码编写。
9)下载高性能网络编程框架twisted,笔者强烈推荐,它将使你的网络编程效率提高10倍以上。
10)学习设计模式、操作系统知识比如线程、进程、同步等。
要想真正掌握计算机技术,并在IT行业里干出一番事业来,有所作为,具有一定的编程能力是一个基本条件和要求。打好基础学编程要具备一定的基础,总结之有以下几方面:
(1)数学基础 从计算机发展和应用的历史来看计算机的数学模型和体系结构等都是有数学家提出的,最早的计算机也是为数值计算而设计的。因此,要学好计算机就要有一定的数学基础,出学者有高中水平就差不多了。
(2)逻辑思维能力的培养 学程序设计要有一定的逻辑思维能力,“逻思力”的培养要长时间的实践锻炼。要想成为一名优秀的程序员,最重要的是掌握编程思想。要做到这一点必须在反复的实践、观察、分析、比较、总结中逐渐地积累。因此在学习编程过程中,我们不必等到什么都完全明白了才去动手实践,只要明白了大概,就要敢于自己动手去体验。谁都有第一次。
有些问题只有通过实践后才能明白,也只有实践才能把老师和书上的知识变成自己的,高手都是这样成材的。
㈨ Python 网络客户端和服务端udp和select都能实现并发,有啥区别呢!
简单来说:没什么区别!因为UDP本来就是报文,也就是“发出后不管”,因此返回极快,根本不会阻塞进程,接收时也是检查一下缓冲区后立刻返回,同样不阻塞进程。既然都是不阻塞进程的,因此select也就多余了!