㈠ 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也就多餘了!