网络编程:检验TCP套接字的传输效率
网络编程:检验TCP套接字的传输效率
1.直接跳转到第1题的Linux端代码
2.直接跳转到第1题的Windows端代码
3.直接跳转到第2题的Linux端代码
4.直接跳转到第2题的Windows端代码
一、实验目的
- 熟悉TCP套接字程序的编写过程。
- 在Linux或者Windows操作系统上编写服务器端/客户端程序。检验发送大数据时,接收缓存大小以及I/O函数调用次数与数据传输效率之间的关系。
二、实验内容
1、在Linux或者Windows操作系统上修改实验一程序,检验I/O函数调用次数对程序整体性能的影响。实现以下功能: (1)让服务器端发送固定大小的数据(例如100000字节)。(2)修改客户端程序,增加用户对接收字节数的配置功能。运行客户端程序时除了IP地址和端口号,增加第3个输入参数,指定接收字节数(参考下图客户端运行示例)。程序中根据第3个参数,设置接收字节数并以此参数作为单位长度接收服务器端发送来的数据。接收字节数应分别设置为1000、100、10、1字节。(3)统计并打印输出接收的总字节数和所消耗的时间。(4)根据实验结果,分析I/O函数调用次数对传输效率的影响。
2、在Linux或者Windows操作系统上修改实验一程序,检验接收缓存大小对数据传输效率的影响。实现以下功能:(1)让客户端发送固定大小的数据(例如分10次,每次发送10000字节)。(2)修改服务器端程序,增加用户对接收缓存大小的配置功能。运行服务器端程序时要输入端口号和接收缓存的大小(包括100字节、10000字节、100000字节),程序中根据用户输入的数据设置接收缓存,并以此参数作为单位长度接收客户端发送来的数据。每次接收后设置100ms的间隔时间。(3)统计并打印输出接收的总字节数和所消耗的时间。(4)根据实验结果,分析不同的接收缓存大小对传输效率的影响。
实验结果
根据实验结果分析I/O函数调用次数对传输效率的影响,分析不同的接收缓存大小对传输效率的影响。
答:在传输相同大小数据情况下,I/O函数调用次数越多,效率越低,传输时间越多,反之则反。接受缓存越小,效率越低,传输时间越多,反之则反。
第一题:
Linux端效果图如下:
Linux端的(采用UOS+VScode+g++)
Linux端代码如下:
1. 服务器端:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
using namespace std;
int main() {
//创建套接字
int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
/////
int opt = 1;
setsockopt(serv_sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof( opt ));
/*Socket 端口被占用解决方法,将套接字属性设置为 SO_REUSEADDR (允许套接口和一个已在使用中的地址捆绑)*/
//将套接字和IP、端口绑定
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
//每个字节都用0填充
serv_addr.sin_family = AF_INET;
//使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//具体的IP地址
serv_addr.sin_port = htons(1113);
//端口
bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
//进入监听状态,等待用户发起请求
listen(serv_sock, 20);
//接收客户端请求
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_size = sizeof(clnt_addr);
int clnt_sock= accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
char str[100000];
for (int i=0; i<100000; i++)
str[i] = '1';
//向客户端发送数据
write(clnt_sock, str, sizeof(str));
//关闭套接字
close(clnt_sock);
close(serv_sock);
return 0;
}
2. 客户端:
#include <time.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
using namespace std;
int main() {
time_t c_start,c_end;
//创建套接字
int client = socket(AF_INET, SOCK_STREAM, 0);
int num;
int count=0;
//向服务器(特定的IP和端口)发起请求
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
//每个字节都用0填充
serv_addr.sin_family = AF_INET;
//使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//具体的IP地址
serv_addr.sin_port = htons(1113);
//端口
cout<<"请输入指定的接收字节数:";
cin>>num;
connect(client, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
//读取服务器传回的数据
c_start = clock();
//!< 单位为ms
while(true) {
char buffer[11000]= {
0
}
;
read(client, buffer,num);
count+=strlen(buffer);
if(*buffer=='\0') {
char buffer[11000]= {
0
}
;
break;
}
}
c_end = clock();
cout<<"共接受:"<<count<<"个字节数据"<<endl;
cout<<"耗时:"<<difftime(c_end,c_start)<<"ms"<<endl;
//关闭套接字
close(client);
return 0;
}
Windows端效果图如下:
Windows端代码如下:
1. 服务器端:
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll
using namespace std;
int main(){
WORD sockVersion = MAKEWORD(2,2);
WSADATA wsaData;//加载Winsock库
//初始化socket资源
if(WSAStartup(sockVersion, &wsaData)!=0){
return 0; //失败
}
//创建套接字
SOCKET serverSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
int opt = 1;
setsockopt(serverSock,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof( opt ));//Socket 端口被占用解决方法,将套接字属性设置为 SO_REUSEADDR (允许套接口和一个已在使用中的地址捆绑)
//绑定套接字
sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充
sockAddr.sin_family = PF_INET; //使用IPv4地址
sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //使用本地的IP地址
sockAddr.sin_port = htons(1234); //端口
bind(serverSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
//进入监听状态
listen(serverSock, 20);
//接收客户端请求
SOCKADDR clntAddr;
int nSize = sizeof(SOCKADDR);
SOCKET clntSock = accept(serverSock, (SOCKADDR*)&clntAddr, &nSize);
char str[100000];
for(int i=0; i<100000; i++)
str[i] = '1';
//向客户端发送数据
send(clntSock, str, strlen(str), NULL);
//关闭套接字
closesocket(clntSock);
closesocket(serverSock);
WSACleanup();//释放Winsock库
system("pause");
return 0;
}
2. 客户端
#include <time.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll
using namespace std;
int main(){
time_t c_start,c_end;
WORD sockVersion = MAKEWORD(2,2);
WSADATA wsaData;//加载Winsock库
//初始化socket资源
if(WSAStartup(sockVersion, &wsaData)!=0){
return 0; //失败
}
//创建套接字
SOCKET sclient = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
int num;
int count=0;
if(sclient == INVALID_SOCKET)
{
cout<<"创建失败!"<<endl;
return 0;
}
//向服务器发起请求
sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充
sockAddr.sin_family = PF_INET; //使用IPv4地址
sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");//使用本地的IP地址
sockAddr.sin_port = htons(1234);//端口
cout<<"请输入指定的接收字节数:";
cin>>num;
connect(sclient, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
//读取服务器传回的数据
c_start = clock(); //!< 单位为ms
while(true){
char buffer[11000]={0};
recv(sclient, buffer, num, NULL);
count+=strlen(buffer);
if(*buffer=='\0'){
char buffer[11000]={0};
break;
}
}
c_end = clock();
//输出接收到的数据
cout<<"共接受:"<<count<<"个字节数据"<<endl;
cout<<"耗时:"<<difftime(c_end,c_start)<<"ms"<<endl;
//关闭套接字
closesocket(sclient);
WSACleanup();//释放Winsock库
system("pause");
return 0;
}
第二题:
Linux端效果图如下:
Linux端的(采用UOS+VScode+g++)
Linux端代码如下:
1. 服务器端:
#include <time.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
#include <netinet/in.h>
using namespace std;
int main() {
time_t c_start,c_end;
//创建套接字
int serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
///
int opt = 1;
setsockopt(serv_sock,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof( opt ));
/*Socket 端口被占用解决方法,将套接字属性设置为 SO_REUSEADDR (允许套接口和一个已在使用中的地址捆绑)*/
int num;
int count=0;
//将套接字和IP、端口绑定
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
//每个字节都用0填充
serv_addr.sin_family = AF_INET;
//使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//具体的IP地址
serv_addr.sin_port = htons(1234);
//端口
cout<<"请输入指定的接收缓存:";
cin>>num;
bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
//进入监听状态,等待用户发起请求
listen(serv_sock, 20);
//接收客户端请求
struct sockaddr_in clnt_addr;
socklen_t clnt_addr_size = sizeof(clnt_addr);
int clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);
//从客户端接收数据
c_start = clock();
//!< 单位为ms
while(true) {
char str[110000]= {
0
}
;
read(clnt_sock, str,num);
count+=strlen(str);
if(*str=='\0')
break;
sleep(0.1);
}
c_end = clock();
cout<<"共接受:"<<count<<"个字节数据"<<endl;
cout<<"耗时:"<<difftime(c_end,c_start)<<"ms"<<endl;
//关闭套接字
close(clnt_sock);
close(serv_sock);
return 0;
}
//g++ 网络编程作业4服务器端.cpp -o test2
2. 客户端:
#include <time.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <unistd.h>
#include <arpa/inet.h>
#include <sys/socket.h>
using namespace std;
int main() {
time_t c_start,c_end;
//创建套接字
int client = socket(AF_INET, SOCK_STREAM, 0);
int count=0;
//向服务器(特定的IP和端口)发起请求
struct sockaddr_in serv_addr;
memset(&serv_addr, 0, sizeof(serv_addr));
//每个字节都用0填充
serv_addr.sin_family = AF_INET;
//使用IPv4地址
serv_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//具体的IP地址
serv_addr.sin_port = htons(1234);
//端口
connect(client, (struct sockaddr*)&serv_addr, sizeof(serv_addr));
//向服务器传送的数据
char buffer[11000];
for (int i=0; i<11000; i++)
buffer[i] = '1';
c_start = clock();
//!< 单位为ms
while(true) {
write(client, buffer, sizeof(buffer));
count++;
cout<<"客户端第"<<count<<"次发送"<<sizeof(buffer)<<"字节数据"<<endl;
if(count==10) {
c_end = clock();
cout<<"共发送"<<sizeof(buffer)*10<<"字节数据,共耗时:"<<difftime(c_end,c_start)<<"ms"<<endl;
break;
}
}
//关闭套接字
close(client);
return 0;
}
//g++ 网络编程作业4客户端.cpp -o test1
Windows端效果图如下:
Windows端代码如下:
1. 服务器端:
#include <time.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <winsock2.h>
#pragma comment (lib, "ws2_32.lib") //加载 ws2_32.dll
using namespace std;
int main(){
time_t c_start,c_end;
WORD sockVersion = MAKEWORD(2,2);
WSADATA wsaData;//加载Winsock库
//初始化socket资源
if(WSAStartup(sockVersion, &wsaData)!=0){
return 0; //失败
}
//创建套接字
SOCKET serverSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
int opt = 1;
setsockopt(serverSock,SOL_SOCKET,SO_REUSEADDR,(char *)&opt,sizeof( opt ));//Socket 端口被占用解决方法,将套接字属性设置为 SO_REUSEADDR (允许套接口和一个已在使用中的地址捆绑)
int num;
int count=0;
//绑定套接字
sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充
sockAddr.sin_family = PF_INET; //使用IPv4地址
sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1"); //使用本地的IP地址
sockAddr.sin_port = htons(1234); //端口
cout<<"请输入指定的接收缓存:";
cin>>num;
bind(serverSock, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
//进入监听状态
listen(serverSock, 20);
//接收客户端请求
SOCKADDR clntAddr;
int nSize = sizeof(SOCKADDR);
SOCKET clntSock = accept(serverSock, (SOCKADDR*)&clntAddr, &nSize);
char str[100000];
for(int i=0; i<100000; i++)
str[i] = '1';
//从客户端接收数据
c_start = clock(); //!< 单位为ms
while(true){
char str[110000]={0};
recv(clntSock, str, num, NULL);
count+=strlen(str);
if(*str=='\0')
break;
Sleep(0.1);
}
c_end = clock();
cout<<"共接受:"<<count<<"个字节数据"<<endl;
cout<<"耗时:"<<difftime(c_end,c_start)<<"ms"<<endl;
//关闭套接字
closesocket(clntSock);
closesocket(serverSock);
WSACleanup();//释放Winsock库
system("pause");
return 0;
}
2. 客户端
#include <time.h>
#include <iostream>
#include <cstring>
#include <cstdlib>
#include <WinSock2.h>
#pragma comment(lib, "ws2_32.lib") //加载 ws2_32.dll
using namespace std;
int main(){
time_t c_start,c_end;
WORD sockVersion = MAKEWORD(2,2);
WSADATA wsaData;//加载Winsock库
//初始化socket资源
if(WSAStartup(sockVersion, &wsaData)!=0){
return 0; //失败
}
//创建套接字
SOCKET sclient = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
int count=0;
if(sclient == INVALID_SOCKET)
{
cout<<"创建失败!"<<endl;
return 0;
}
//向服务器发起请求
sockaddr_in sockAddr;
memset(&sockAddr, 0, sizeof(sockAddr)); //每个字节都用0填充
sockAddr.sin_family = PF_INET; //使用IPv4地址
sockAddr.sin_addr.s_addr = inet_addr("127.0.0.1");//使用本地的IP地址
sockAddr.sin_port = htons(1234);//端口
connect(sclient, (SOCKADDR*)&sockAddr, sizeof(SOCKADDR));
//向服务器传送的数据
char buffer[11000];
for(int i=0; i<11000; i++)
buffer[i] = '1';
c_start = clock(); //!< 单位为ms
while(true){
send(sclient, buffer, strlen(buffer), NULL);
count++;
cout<<"客户端第"<<count<<"次发送"<<sizeof(buffer)<<"字节数据"<<endl;
if(count==10){
c_end = clock();
cout<<"共发送"<<sizeof(buffer)*10<<"字节数据,共耗时:"<<difftime(c_end,c_start)<<"ms"<<endl;
break;
}
}
//关闭套接字
closesocket(sclient);
WSACleanup();//释放Winsock库
system("pause");
return 0;
}