socket实时类网游 dpdk pktgen发包速率率一般是多少

> 博客详情
前言:在最近一个即将结束的项目中使用到了Socket编程,用于调用另一系统进行处理并返回数据。故把Socket的基础知识总结梳理一遍。
一、TCP/IP协议
  既然是网络编程,涉及几个系统之间的交互,那么首先要考虑的是如何准确的定位到网络上的一台或几台主机,另一个是如何进行可靠高效的数据传输。这里就要使用到TCP/IP协议。
  TCP/IP协议(传输控制协议)由网络层的IP协议和传输层的TCP协议组成。IP层负责网络主机的定位,数据传输的路由,由IP地址可以唯一的确定Internet上的一台主机。TCP层负责面向应用的可靠的或非可靠的数据传输机制,这是网络编程的主要对象。
二、TCP与UDP
  TCP是一种面向连接的保证可靠传输的协议。通过TCP协议传输,得到的是一个顺序的无差错的数据流。发送方和接收方的成对的两个socket之间必须建立连接,以便在TCP协议的基础上进行通信,当一个socket(通常都是server socket)等待建立连接时,另一个socket可以要求进行连接,一旦这两个socket连接起来,它们就可以进行双向数据传输,双方都可以进行发送或接收操作。
  UDP是一种面向无连接的协议,每个数据报都是一个独立的信息,包括完整的源地址或目的地址,它在网络上以任何可能的路径传往目的地,因此能否到达目的地,到达目的地的时间以及内容的正确性都是不能被保证的。
TCP与UDP区别:
  1、TCP是面向连接的协议,通过三次握手建立连接,通讯完成时要拆除连接,由于TCP是面向连接协议,所以只能用于点对点的通讯。而且建立连接也需要消耗时间和开销。
  2、TCP传输数据无大小限制,进行大数据传输。
  3、TCP是一个可靠的协议,它能保证接收方能够完整正确地接收到发送方发送的全部数据。
  1、UDP是面向无连接的通讯协议,UDP数据包括目的端口号和源端口号信息,由于通讯不需要连接,所以可以实现广播发送。
  2、UDP传输数据时有大小限制,每个被传输的数据报必须限定在64KB之内。
  3、UDP是一个不可靠的协议,发送方所发送的数据报并不一定以相同的次序到达接收方。
TCP与UDP应用:
  1、TCP在网络通信上有极强的生命力,例如远程连接(Telnet)和文件传输(FTP)都需要不定长度的数据被可靠地传输。但是可靠的传输是要付出代价的,对数据内容正确性的检验必然占用计算机的处理时间和网络的带宽,因此TCP传输的效率不如UDP高。
  2,UDP操作简单,而且仅需要较少的监护,因此通常用于局域网高可靠性的分散系统中client/server应用程序。例如视频会议系统,并不要求音频视频数据绝对的正确,只要保证连贯性就可以了,这种情况下显然使用UDP会更合理一些。
三、Socket是什么
  Socket通常也称作"套接字",用于描述IP地址和端口,是一个通信链的句柄。网络上的两个程序通过一个双向的通讯连接实现数据的交换,这个双向链路的一端称为一个Socket,一个Socket由一个IP地址和一个端口号唯一确定。应用程序通常通过"套接字"向网络发出请求或者应答网络请求。&Socket是TCP/IP协议的一个十分流行的编程界面,但是,Socket所支持的协议种类也不光TCP/IP一种,因此两者之间是没有必然联系的。在Java环境下,Socket编程主要是指基于TCP/IP协议的网络编程。
  Socket通讯过程:服务端监听某个端口是否有连接请求,客户端向服务端发送连接请求,服务端收到连接请求向客户端发出接收消息,这样一个连接就建立起来了。客户端和服务端都可以相互发送消息与对方进行通讯。
  Socket的基本工作过程包含以下四个步骤:
  1、创建Socket;
  2、打开连接到Socket的输入输出流;
  3、按照一定的协议对Socket进行读写操作;
  4、关闭Socket。
四、Java中的Socket
  在java.net包下有两个类:Socket和ServerSocket。ServerSocket用于服务器端,Socket是建立网络连接时使用的。在连接成功时,应用程序两端都会产生一个Socket实例,操作这个实例,完成所需的会话。对于一个网络连接来说,套接字是平等的,并没有差别,不因为在服务器端或在客户端而产生不同级别。不管是Socket还是ServerSocket它们的工作都是通过SocketImpl类及其子类完成的。
列出几个常用的构造方法:
Socket(InetAddress address,int&port);//创建一个流套接字并将其连接到指定 IP 地址的指定端口号
Socket(String host,int&port);//创建一个流套接字并将其连接到指定主机上的指定端口号
Socket(InetAddress address,int&port, InetAddress localAddr,int&localPort);//创建一个套接字并将其连接到指定远程地址上的指定远程端口
Socket(String host,int&port, InetAddress localAddr,int&localPort);//创建一个套接字并将其连接到指定远程主机上的指定远程端口
Socket(SocketImpl impl);//使用用户指定的 SocketImpl 创建一个未连接 Socket
ServerSocket(int&port);//创建绑定到特定端口的服务器套接字
ServerSocket(int&port,int&backlog);//利用指定的 backlog 创建服务器套接字并将其绑定到指定的本地端口号
ServerSocket(int&port,int&backlog, InetAddress bindAddr);//使用指定的端口、侦听 backlog 和要绑定到的本地 IP地址创建服务器
  构造方法的参数中,address、host和port分别是双向连接中另一方的IP地址、主机名和端&口号,stream指明socket是流socket还是数据报socket,localPort表示本地主机的端口号,localAddr和bindAddr是本地机器的地址(ServerSocket的主机地址),impl是socket的父类,既可以用来创建serverSocket又可以用来创建Socket。count则表示服务端所能支持的最大连接数。
注意:必须小心选择端口号。每一个端口提供一种特定的服务,只有给出正确的端口,才&能获得相应的服务。0~1023的端口号为系统所保留,例如http服务的端口号为80,telnet服务的端口号为21,ftp服务的端口号为23,&所以我们在选择端口号时,最好选择一个大于1023的数以防止发生冲突。
几个重要的Socke方法:
public&InputStream getInputStream();//方法获得网络连接输入,同时返回一个IutputStream对象实例
public&OutputStream getOutputStream();//方法连接的另一端将得到输入,同时返回一个OutputStream对象实例
public&Socket accept();//用于产生"阻塞",直到接受到一个连接,并且返回一个客户端的Socket对象实例。
"阻塞"是一个术语,它使程序运行暂时"停留"在这个地方,直到一个会话产生,然后程序继续;通常"阻塞"是由循环产生的。
注意:其中getInputStream和getOutputStream方法均会产生一个IOException,它必须被捕获,因为它们返回的流对象,通常都会被另一个流对象使用。
五、基本的Client/Server程序
以下是一个基本的客户端/服务器端程序代码。主要实现了服务器端一直监听某个端口,等待客户端连接请求。客户端根据IP地址和端口号连接服务器端,从键盘上输入一行信息,发送到服务器端,然后接收服务器端返回的信息,最后结束会话。这个程序一次只能接受一个客户连接。
ps:这个小例子写好后,服务端一直接收不到消息,调试了好长时间,才发现误使用了PrintWriter的print()方法,而BufferedReader的readLine()方法一直没有遇到换行,所以一直等待读取。我晕死~~@_@
客户端程序:
import java.io.BufferedR
import java.io.InputStreamR
import java.io.PrintW
import java.net.S
public class SocketClient {
public static void main(String[] args) {
/** 创建Socket*/
// 创建一个流套接字并将其连接到指定 IP 地址的指定端口号(本处是本机)
Socket socket =new Socket("127.0.0.1",2013);
// 60s超时
socket.setSoTimeout(60000);
/** 发送客户端准备传输的信息 */
// 由Socket对象得到输出流,并构造PrintWriter对象
PrintWriter printWriter =new PrintWriter(socket.getOutputStream(),true);
// 将输入读入的字符串输出到Server
BufferedReader sysBuff =new BufferedReader(new InputStreamReader(System.in));
printWriter.println(sysBuff.readLine());
// 刷新输出流,使Server马上收到该字符串
printWriter.flush();
/** 用于获取服务端传输来的信息 */
// 由Socket对象得到输入流,并构造相应的BufferedReader对象
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 输入读入一字符串
String result = bufferedReader.readLine();
System.out.println("Server say : " + result);
/** 关闭Socket*/
printWriter.close();
bufferedReader.close();
socket.close();
}catch (Exception e) {
System.out.println("Exception:" + e);
服务器端程序:
import java.io.BufferedR
import java.io.InputStreamR
import java.io.PrintW
import java.net.ServerS
import java.net.S
public class SocketServer {
public static void main(String[] args) {
/** 创建ServerSocket*/
// 创建一个ServerSocket在端口2013监听客户请求
ServerSocket serverSocket =new ServerSocket(2013);
while (true) {
// 侦听并接受到此Socket的连接,请求到来则产生一个Socket对象,并继续执行
Socket socket = serverSocket.accept();
/** 获取客户端传来的信息 */
// 由Socket对象得到输入流,并构造相应的BufferedReader对象
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream()));
// 获取从客户端读入的字符串
String result = bufferedReader.readLine();
System.out.println("Client say : " + result);
/** 发送服务端准备传输的 */
// 由Socket对象得到输出流,并构造PrintWriter对象
PrintWriter printWriter =new PrintWriter(socket.getOutputStream());
printWriter.print("hello Client, I am Server!");
printWriter.flush();
/** 关闭Socket*/
printWriter.close();
bufferedReader.close();
socket.close();
}catch (Exception e) {
System.out.println("Exception:" + e);
serverSocket.close();
六、多客户端连接服务器
上面的服务器端程序一次只能连接一个客户端,这在实际应用中显然是不可能的。通常的网络环境是多个客户端连接到某个主机进行通讯,所以我们要对上面的程序进行改造。
设计思路:服务器端主程序监听某一个端口,客户端发起连接请求,服务器端主程序接收请求,同时构造一个线程类,用于接管会话。当一个Socket会话产生后,这个会话就会交给线程进行处理,主程序继续进行监听。
下面的实现程序流程是:客户端和服务器建立连接,客户端发送消息,服务端根据消息进行处理并返回消息,若客户端申请关闭,则服务器关闭此连接,双方通讯结束。
客户端程序:
import java.io.BufferedR
import java.io.InputStreamR
import java.io.PrintW
import java.net.S
public class SocketClient {
public static void main(String[] args) {
Socket socket =new Socket("127.0.0.1",2013);
socket.setSoTimeout(60000);
PrintWriter printWriter =new PrintWriter(socket.getOutputStream(),true);
BufferedReader bufferedReader =new BufferedReader(new InputStreamReader(socket.getInputStream()));
String result ="";
while(result.indexOf("bye") == -1){
BufferedReader sysBuff =new BufferedReader(new InputStreamReader(System.in));
printWriter.println(sysBuff.readLine());
printWriter.flush();
result = bufferedReader.readLine();
System.out.println("Server say : " + result);
printWriter.close();
bufferedReader.close();
socket.close();
}catch (Exception e) {
System.out.println("Exception:" + e);
服务器端程序:
import java.io.*;
import java.net.*;
public class Server extends ServerSocket {
private static final int SERVER_PORT =2013;
public Server()throws IOException {
super(SERVER_PORT);
while (true) {
Socket socket = accept();
new CreateServerThread(socket);//当有请求时,启一个线程处理
}catch (IOException e) {
}finally {
class CreateServerThread extends Thread {
private BufferedReader bufferedR
private PrintWriter printW
public CreateServerThread(Socket s)throws IOException {
bufferedReader =new BufferedReader(new InputStreamReader(client.getInputStream()));
printWriter =new PrintWriter(client.getOutputStream(),true);
System.out.println("Client(" + getName() +") come in...");
public void run() {
String line = bufferedReader.readLine();
while (!line.equals("bye")) {
printWriter.println("continue, Client(" + getName() +")!");
line = bufferedReader.readLine();
System.out.println("Client(" + getName() +") say: " + line);
printWriter.println("bye, Client(" + getName() +")!");
System.out.println("Client(" + getName() +") exit!");
printWriter.close();
bufferedReader.close();
client.close();
}catch (IOException e) {
public static void main(String[] args)throws IOException {
new Server();
七、信息共享
以上虽然实现了多个客户端和服务器连接,但是仍然是消息在一个客户端和服务器之间相互传播。现在我们要实现信息共享,即服务器可以向多个客户端发送广播消息,客户端也可以向其他客户端发送消息。类似于聊天室的那种功能,实现信息能在多个客户端之间共享。
设计思路:客户端循环可以不停输入向服务器发送消息,并且启一个线程,专门用来监听服务器端发来的消息并打印输出。服务器端启动时,启动一个监听何时需要向客户端发送消息的线程。每次接受客户端连接请求,都启一个线程进行处理,并且将客户端信息存放到公共集合中。当客户端发送消息时,服务器端将消息顺序存入队列中,当需要输出时,从队列中取出广播到各客户端处。客户端输入showuser命令可以查看在线用户列表,输入bye向服务器端申请退出连接。
PS:以下代码在测试时发现了一个中文乱码小问题,当文件设置UTF-8编码时,无论怎样在代码中设置输入流编码都不起作用,输入中文仍然会乱码。把文件设置为GBK编码后,不用在代码中设置输入流编码都能正常显示传输中文。
客户端代码:
import java.io.BufferedR
import java.io.InputStreamR
import java.io.PrintW
import java.net.S
public class SocketClient extends Socket{
private static final String SERVER_IP ="127.0.0.1";
private static final int SERVER_PORT =2013;
private PrintW
private BufferedR
* 与服务器连接,并输入发送消息
public SocketClient()throws Exception{
super(SERVER_IP, SERVER_PORT);
out =new PrintWriter(this.getOutputStream(),true);
in =new BufferedReader(new InputStreamReader(this.getInputStream()));
new readLineThread();
while(true){
in =new BufferedReader(new InputStreamReader(System.in));
String input = in.readLine();
out.println(input);
* 用于监听服务器端向客户端发送消息线程类
class readLineThread extends Thread{
private BufferedR
public readLineThread(){
buff =new BufferedReader(new InputStreamReader(client.getInputStream()));
}catch (Exception e) {
public void run() {
while(true){
String result = buff.readLine();
if("byeClient".equals(result)){//客户端申请退出,服务端返回确认退出
}else{//输出服务端发送消息
System.out.println(result);
in.close();
out.close();
client.close();
}catch (Exception e) {
public static void main(String[] args) {
new SocketClient();//启动客户端
}catch (Exception e) {
服务器端代码:
import java.io.BufferedR
import java.io.IOE
import java.io.InputStreamR
import java.io.PrintW
import java.net.ServerS
import java.net.S
import java.util.ArrayL
import java.util.LinkedL
import java.util.L
public class Server extends ServerSocket{
private static final int SERVER_PORT =2013;
private static boolean isPrint =//是否输出消息标志
private static List user_list =new ArrayList();//登录用户集合
private static List&ServerThread& thread_list =new ArrayList&ServerThread&();//服务器已启用线程集合
private static LinkedList&String& message_list =new LinkedList&String&();//存放消息队列
* 创建服务端Socket,创建向客户端发送消息线程,监听客户端请求并处理
public Server()throws IOException{
super(SERVER_PORT);//创建ServerSocket
new PrintOutThread();//创建向客户端发送消息线程
while(true){//监听客户端请求,启个线程处理
Socket socket = accept();
new ServerThread(socket);
}catch (Exception e) {
* 监听是否有输出消息请求线程类,向客户端发送消息
class PrintOutThread extends Thread{
public PrintOutThread(){
public void run() {
while(true){
if(isPrint){//将缓存在队列中的消息按顺序发送到各客户端,并从队列中清除。
String message = message_list.getFirst();
for (ServerThread thread : thread_list) {
thread.sendMessage(message);
message_list.removeFirst();
isPrint = message_list.size() &0 ?true :
* 服务器线程类
class ServerThread extends Thread{
private PrintW
private BufferedR
public ServerThread(Socket s)throws IOException{
out =new PrintWriter(client.getOutputStream(),true);
in =new BufferedReader(new InputStreamReader(client.getInputStream()));
in.readLine();
out.println("成功连上聊天室,请输入你的名字:");
public void run() {
int flag =0;
String line = in.readLine();
while(!"bye".equals(line)){
//查看在线用户列表
if ("showuser".equals(line)) {
out.println(this.listOnlineUsers());
line = in.readLine();
//第一次进入,保存名字
if(flag++ ==0){
user_list.add(name);
thread_list.add(this);
out.println(name +"你好,可以开始聊天了...");
this.pushMessage("Client&" + name +"&进入聊天室...");
this.pushMessage("Client&" + name +"& say : " + line);
line = in.readLine();
out.println("byeClient");
}catch (Exception e) {
e.printStackTrace();
}finally{//用户退出聊天室
client.close();
}catch (IOException e) {
e.printStackTrace();
thread_list.remove(this);
user_list.remove(name);
pushMessage("Client&" + name +"&退出了聊天室");
//放入消息队列末尾,准备发送给客户端
private void pushMessage(String msg){
message_list.addLast(msg);
//向客户端发送一条消息
private void sendMessage(String msg){
out.println(msg);
//统计在线用户列表
private String listOnlineUsers() {
String s ="--- 在线用户列表 ---\015\012";
for (int i =0; i & user_list.size(); i++) {
s +="[" + user_list.get(i) +"]\015\012";
s +="--------------------";
public static void main(String[] args)throws IOException {
new Server();//启动服务端
八、文件传输
客户端向服务器端传送文件,服务端可获取文件名用于保存,获取文件大小计算传输进度,比较简单,直接贴代码。
客户端代码:
import java.io.DataOutputS
import java.io.F
import java.io.FileInputS
import java.net.S
public class Client extends Socket{
private static final String SERVER_IP ="127.0.0.1";
private static final int SERVER_PORT =2013;
private FileInputS
private DataOutputS
public Client(){
client =new Socket(SERVER_IP, SERVER_PORT);
//向服务端传送文件
File file =new File("c:/test.doc");
fis =new FileInputStream(file);
dos =new DataOutputStream(client.getOutputStream());
//文件名和长度
dos.writeUTF(file.getName());
dos.flush();
dos.writeLong(file.length());
dos.flush();
//传输文件
byte[] sendBytes =new byte[1024];
int length =0;
while((length = fis.read(sendBytes,0, sendBytes.length)) &0){
dos.write(sendBytes,0, length);
dos.flush();
}catch (Exception e) {
e.printStackTrace();
if(fis !=null)
fis.close();
if(dos !=null)
dos.close();
client.close();
}catch (Exception e) {
e.printStackTrace();
public static void main(String[] args)throws Exception {
new Client();
服务器端代码:
import java.io.DataInputS
import java.io.F
import java.io.FileOutputS
import java.net.ServerS
import java.net.S
public class Server extends ServerSocket{
private static final int PORT =2013;
private ServerS
private DataInputS
private FileOutputS
public Server()throws Exception{
server =new ServerSocket(PORT);
while(true){
client = server.accept();
dis =new DataInputStream(client.getInputStream());
//文件名和长度
String fileName = dis.readUTF();
long fileLength = dis.readLong();
fos =new FileOutputStream(new File("d:/" + fileName));
byte[] sendBytes =new byte[1024];
int transLen =0;
System.out.println("----开始接收文件&" + fileName +"&,文件大小为&" + fileLength +"&----");
while(true){
int read =0;
read = dis.read(sendBytes);
if(read == -1)
transLen +=
System.out.println("接收文件进度" +100 * transLen/fileLength +"%...");
fos.write(sendBytes,0, read);
fos.flush();
System.out.println("----接收文件&" + fileName +"&成功-------");
client.close();
}catch (Exception e) {
e.printStackTrace();
}finally {
if(dis !=null)
dis.close();
if(fos !=null)
fos.close();
server.close();
}catch (Exception e) {
e.printStackTrace();
public static void main(String[] args)throws Exception {
new Server();
推荐阅读:
100万并发连接服务器笔记之Java Netty处理1M连接会怎么样
人打赏支持
码字总数 338244
支付宝支付
微信扫码支付
打赏金额: ¥
已支付成功
打赏金额: ¥用socket&tcp基于互联网和局域网方式传输文件,如果传输文件,使得传输速度能够最快,怎样做.跟传输socket的个数有关吗?单socket在局域网和internet传输时,最快速度是多少,受到哪些因素影响?在internet传输时,传输速度跟带宽的关系是怎样的?如果是基于GPRS拨号上网传输,怎样做使得传输速度最快,谢谢!
回复讨论(解决方案)
TCP&??&加大缓冲区
UDP&??&使劲的发(注意丢包问题)
GPRS&??&这个在于带宽本身,因为它底层还是用的TCP/IP,中间用的是GPRS,到达ISP后又变成TCP/IP了
TCP&??&加大缓冲区
UDP&??&使劲的发(注意丢包问题)
GPRS&??&这个在于带宽本身,因为它底层还是用的TCP/IP,中间用的是GPRS,到达ISP后又变成TCP/IP了
缓冲区到多大是最适合的呢?在GRPS的情况下,由于传输带宽有限,在发送端加大缓冲区,不断的发,接受端能收到所有数据吗?发送端的发送只是把数据压入socket的发送缓冲区
你监测发送过程,如果发的慢了,试试加大缓冲区会不会提高速度
可以动态调整的
TCP/IP的底层协议栈最大允许的缓冲区时64K
GPRS只是负责利用无线技术传输数据,成功或者正确与否它是不管的,需要收发双发来确定,就像TCP和UDP协议一样,都是利用IP包进行传输,但是IP包本身不具备可靠性,所以诞生了TCP
速度是跟硬件相关吧?
而我们写程序是跟硬件无关的
如果真要考虑最大速度
一个考虑cpu处理指令的速度,
一个考虑文件读写速度,
一个是网卡传输速度,
还有一个mtu,以及分包重组这些东东,
但很多东西都是远小于发送文件包的长度,可以忽略不去考虑
TCP/IP的底层协议栈最大允许的缓冲区时64K
GPRS只是负责利用无线技术传输数据,成功或者正确与否它是不管的,需要收发双发来确定,就像TCP和UDP协议一样,都是利用IP包进行传输,但是IP包本身不具备可靠性,所以诞生了TCP
谢谢指点!GPRS负责无线技术传输,其传输的速度的上限和下限决定了文件传输的速度最大值,这样理解对吧?如果是,加入GPRS的上传最大限为10K/S,ADSL为100K/S,怎样写程序,让程序自动根据带宽,以最大的速度上传?请指点
多线程传,但是在硬件条件最大传输速度的限制能6477人阅读
C/C++(1)
(一)、目标
做一个以精确速率向外输出数据的数据源,要完成这个目标,最基础的是:
、找到一种精确的计时器,在精确的时间范围内控制数据源以指定的速度向外发送数据。
、通过对套接字选项和线程优先级的设置减少网络因素对发送速度造成的影响,从而提高发送精度,保证数据的实际发送量尽可能的达到指定的理论发送量。
&&&& 针对第一个要求,通过寻找到一种时间精度达到微秒级的精确计数器来保证,在硬件支持的情况下可以通过获取时钟频率以及震荡次数,通过在事件两端分别调用函数得到震荡次数的差值并结合时钟频率可以计算出精确的时间间隔,通过指定的传输速度和精确的延时可以计算出需要发送的数据量。对于第二个要求通过设置数据源所在线程的优先级,以及对套接字选项的设置来减小协议本身对数据传输的过多控制而造成的时延,从而使实际的数据发送量尽可能的接近理论值。
(一)、设置线程优先级
首先在主函数中创建线程函数,在线程函数中实现数据源的功能,线程创建成功后对线程优先级进行设置,下对线程优先级进行设置的函数为,其中定义了线程的优先级。
线程优先级
优先级值
如果进程优先级为则调整为,其他情况为
(在原有基础上)
(低于标准)
(在原有基础上)
不变(取进程优先级)
(高于标准)
(在原有基础上)
(在原有基础上)
如果进程优先级为则调整为,其他情况为
将线程优先级设置为最高级,即,排除本地其他进程的干扰,使得操作系统能够优先调度。
(二)、使用高精度计数器
要实现精确的发送速度,需要有精确的时间控制,在一般情况下使用以下两种方式就满足要求了。一是用函数建立一个定时器后,在程序中通过处理有定时器发送到线程的消息队列中的消息,而得到定时的效果。二是利用函数可以返回计算机启动后的时间,通过两次调用函数,然后控制他们的差值来取得定时的效果。但是以上两种方法都是毫秒级的,在内部有一个高精度运行计时器(),利用它可以获得高精度的定时间隔,其精度可以达到微秒级,其精度与的时钟频率有关。利用函数能够得到这个定时器的频率。利用函数能够得到定时器的当前值,根据要延时的时间和定时器的频率,能够算出定时器要经过的周期数,循环指定的周期数,就达到了高精度定时的目的。以下是这个函数的原型:
作用返回硬件支持的高精度计数器的频率。
返回值:如果硬件支持高精度计数器则返回频率值,若硬件不支持返回零。
QueryPerformanceCounter(LARGE_INTEGER*lpPerformanceCount);
&&& 作用:得到高精度计时器的值。
&&& 返回值:如果安装的硬件支持高精度计时器则函数返回计数器的值,如果硬件不支持参数返回零。
采用这种方法的步骤如下:
首先调用函数取得高精度运行计数器的频率,单位是每秒多少次()此数一般很大,在实验主机上此频率值为。
在循环之外先调用一次,得到计数器的值,在之前调用循环调用,得到计数器的值,两次数值的差值通过计数器的频率换算成时间间隔,。当达到指定的大小后跳出循环,并将此时的赋给,重新进入循环计时,发送的数据大小根据指定的速度与定时时间确定。
这种方法存在一个致命的问题,就是忙等,循环过程会占满CPU资源。因此需要调整一下算法,循环过程引入休眠机制,降低CPU占用,但是休眠机制由于操作系统调度的不确定性,会造成循环结束后的实际时间和预设时间会有差别。没有关系,我们在循环结束后调用,重新计算本次和上次循环的精确时间差,运用这个时间来计算send发送的数据大小,这样保证输出的数据始终恒定。
(三)设置套接字选项
:通过设置该选项可以改变发送缓冲区的大小,根据应用需求,设置合理的缓冲区大小能够有效提高数据发送的效率。
:在默认情况下,协议栈发送数据采用算法,这样做虽然提高了网络的吞吐量,但是实时性却降低了,如果设置了选项,就会禁用算法,应用程序调用发送的数据包会被立即投送到网络,而没有延迟。考虑到程序中需要做到精确发送的要求,所以将选项设置为。
:通过设置该选项,可以绕过路由表中的网关所在的表项,设置了该套接字选项的可以将数据包不经网关发送,而是发往直接相连的主机。该套接字选项的合法的值是整数形式的布尔标志值,这里设为。
在下,对套接字选项进行设置的函数为
获取当先套接字选项值的函数为
通过以上两个函数可以查看并重新设置套接字选项的值。
当指定传输速度为时,速度的波动控制在了。
当指定传输速度为时,速度的波动在以内。
当指定传输速度为时,速度的波动控制在了之内。
思考与改进:
&&& Socket的通信,数据从发送方到接收方,影响速率的因素很多,主要包括以下几个方面:
1、操作系统调度。
2、其他网络进程对网络带宽资源的争抢。
3、协议本身,如果是TCP协议,则速率控制受到TCP协议流量控制和拥塞控制机制,链路层流量控制机制的影响。
4、协议包在发送和接收途中受到其他网络数据的挤占及丢失等。
&& 我们只能在发送端的应用层以尽可能精确的速率向传输层送速率,然而数据经过传输层、IP层、链路层到物理层最终到网络上,不可控的因素太多。如果能够在网卡驱动层检测实际的进程数据流量,然后根据网卡流量来反馈控制数据投送量,将更为精确地实现速率的控制,具体实现需要进一步研究。
参考知识库
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场
访问:63042次
排名:千里之外
原创:31篇
评论:13条
本人拥有该Blog内全部原创文章的所有权利。欢迎以任何形式转载,但务必注明原文链接。任何个人、组织、网站、出版社不得在未经本人许可的情况下用于商业目的。
(2)(2)(3)(1)(2)(3)(2)(4)(5)(2)(7)}

我要回帖

更多关于 iperf发包速率 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信