关于TCP下SOCKET的一些测试

=============================测试代码===========================

客户端:

#include<winsock2.h> //包含头文件

#include<stdio.h>

#include<windows.h>

#pragma comment(lib,"WS2_32.lib") //显式连接套接字库

int main() //主函数开始

{

WSADATA data; //定义WSADATA结构体对象

WORD w=MAKEWORD(2,0); //定义版本号码

::WSAStartup(w,&data); //初始化套接字库

SOCKET s; //定义连接套接字句柄

char sztext[20]={0};

s=::socket(AF_INET,SOCK_STREAM,0); //创建TCP套接字

sockaddr_in addr; //定义套接字地址结构

addr.sin_family=AF_INET; //初始化地址结构

addr.sin_port=htons(75);

addr.sin_addr.S_un.S_addr=inet_addr("192.168.0.20");

printf("客户端已经启动\r\n"); //输出提示信息

int ret_con = ::connect(s,(sockaddr*)&addr,sizeof(addr));

Sleep(100000);

char t[200]="12345";

int r = ::send(s,t,0,0);

Sleep(1000);

::closesocket(s); //关闭套接字句柄

char buf[100]={0};

int r2 = ::recv(s,buf,100,0);

printf("%s",buf);

::WSACleanup(); //释放套接字库

if(getchar()) //如果有输入,则关闭程序

{

return 0; //正常结束程序

}

else

{

::Sleep(100); //程序睡眠

}

return 0;

}

服务器:

#include<winsock2.h> //包含头文件

#include<stdio.h>

#include<windows.h>

#pragma comment(lib,"WS2_32.lib") //显式连接套接字库

int main() //主函数开始

{

WSADATA data; //定义WSADATA结构体对象

WORD w=MAKEWORD(2,0); //定义版本号码

char sztext[]="你已经连接上"; //定义并初始化发送到客户端的字符数组

::WSAStartup(w,&data); //初始化套接字库

SOCKET s,s1; //定义连接套接字和数据收发套接字句柄

s=::socket(AF_INET,SOCK_STREAM,0); //创建TCP套接字

sockaddr_in addr,addr2; //定义套接字地址结构

int n=sizeof(addr2); //获取套接字地址结构大小

addr.sin_family=AF_INET; //初始化地址结构

addr.sin_port=htons(75);

addr.sin_addr.S_un.S_addr=INADDR_ANY;

::bind(s,(sockaddr*)&addr,sizeof(addr)); //绑定套接字

::listen(s,5); //监听套接字

printf("服务器已经启动\r\n"); //输出提示信息

while(true)

{

s1=::accept(s,(sockaddr*)&addr2,&n); //接受连接请求,正常情况下此函数是个阻塞函数,如果没有阻塞则是此函数运行失败

if(s1!=NULL)

{

printf("%s已经连接上\r\n",inet_ntoa(addr2.sin_addr));

//::send(s1,sztext,sizeof(sztext),0); //向客户端发送字符数组

}

char buf[100]="";

::recv(s1,buf,100,0);

printf("%s",buf);

Sleep(4*1000);

char t[200]="12345";

int r = ::send(s1,t,5,0);

printf("\n%d\n",r);

Sleep(10*1000);

::closesocket(s1);

Sleep(500*60*1000);

::closesocket(s); //关闭套接字句柄

::WSACleanup(); //释放套接字库

if(getchar()) //如果有输入,则关闭程序

{

return 0; //正常结束程序

}

else

{

::Sleep(100); //应用睡眠0.1秒

}

}

}

======================================================================

测试环境:

本机:      WIN7     192.168.0.20

虚拟机:    WINXP   192.168.0.250

抓包工具:  Wireshark

测试内容:

1.客户端连接IP地址不存在或者端口没有开放

IP不存在时Wireshark抓不到数据包

使用下面的代码测试connect返回时间

int t1 = clock();

int ret_con = ::connect(s,(sockaddr*)&addr,sizeof(addr));

int t2 = clock() - t1;

测试结果是20秒

端口不存在时,可以抓到6个数据包

客户端尝试连接3次失败之后不再尝试连接

Connect函数返回时间是1秒

2.正常三次握手的抓包情况

成功抓到三次握手数据包。Connect返回时间为0

3.研究三次握手与accept函数有无关系

研究方法,服务器accept函数上面下断点,单步走,查看抓包情况

accept函数还没有调用已经抓到数据包,实验证明三次握手与accept函数无关

4.客户端简单发送一个数据包

服务器代码:(connect函数之后就一直sleep)

s1=::accept(s,(sockaddr*)&addr2,&n); //接受连接请求,正常情况下此函数是个阻塞函数,如果没有阻塞则是此函数运行失败

if(s1!=NULL)

{

printf("%s已经连接上\r\n",inet_ntoa(addr2.sin_addr));

}

Sleep(1000 * 1000);

一共五条数据,前三条是3次握手,第四条是send发送”12345”的这条数据包,第5条是服务器响应数据包,表示自己已经收到数据了。测试过程中服务器并没来得及调用recv函数,说明TCP协议把数据先接收到了某个缓冲区,等待应用程序来读取。

5.客户端send发送数据为0的情况

服务器代码:

s1=::accept(s,(sockaddr*)&addr2,&n); //接受连接请求,正常情况下此函数是个阻塞函数,如果没有阻塞则是此函数运行失败

if(s1!=NULL)

{

printf("%s已经连接上\r\n",inet_ntoa(addr2.sin_addr));

}

char buf[100]="";

::recv(s1,buf,100,0);

printf("接收到的数据为:%s",buf);

Sleep(400*1000);

客户端代码:

char t[200]="12345";

int r = ::send(s,t,0,0);

客户端方面没有抓到发送出去的数据包,只有握手数据包

服务器方面也没有收到数据包

调用closesocket函数之后客户端给服务发送了一个数据包,服务器发送了响应数据包

由于接收到客户端的closesocket函数,服务器的recv函数立即返回。

6.客户端send函数之后立即调用closesocket函数

直接运行:

可以看到:服务器方面没有响应客户端的send函数(发送相应的ACK数据包)而是直接响应了closesocket数据包。

但不运行:

数据包正常,分析原因应该是TCP的规定,接收到closesocket函数之后不再响应send的数据包

7.客户端连续调用send函数

服务器是否调用recv进行接受,客户端连续发送的数据会分两拨到达

服务器接受缓冲区够大的情况下

8.抓取四次握手释放连接数据包

服务器代码:

s1=::accept(s,(sockaddr*)&addr2,&n); //接受连接请求,正常情况下此函数是个阻塞函数,如果没有阻塞则是此函数运行失败

if(s1!=NULL)

{

printf("%s已经连接上\r\n",inet_ntoa(addr2.sin_addr));

}

Sleep(2*1000);

::closesocket(s1);

客户端代码:

int ret_con = ::connect(s,(sockaddr*)&addr,sizeof(addr));

Sleep(1*1000);

::closesocket(s); //关闭套接字句柄

Sleep(100*1000);

要想抓到四次握手数据包必须一方先close函数,另一方紧接着close函数才可以

9.客户端closesocket之后服务器端一直sleep(不发送相应closesocket)

可以看到服务器端始终没有调用closesocket,120秒之后客户端采取另一个策略,发送RST数据包

时间: 2024-08-12 12:20:22

关于TCP下SOCKET的一些测试的相关文章

netstat统计的tcp连接数与?proc?pid?fd下socket类型fd数量不一致的分析

最近,线上一个应用,发现socket数缓慢增长,并且不回收,超过警告线之后,被运维监控自动重启了. 首先到zabbix上观察JVM历史记录,发现JVM-Perm space最近两周没有数据,猜测是程序从JDK7切换到JDK8了.问过开发人员之后,程序已经很久没有重启了,最近才重新发布的.而在这期间,线上的Java运行环境已经从JDK7升级到JDK8了. 因为jdk8里没有Perm space了,换成了Metaspace. ###netstat到线上服务器上,用netstat来统计进程的conne

Windows Phone 7 下 Socket(TCP) 与 PC 通讯

Windows Phone 7 下 Socket(TCP) 与 PC 通讯,使用 WP7 模拟器与 PC 上的 Simple TCP 服务进行通讯. TCP 客户端主要实现 Socket 连接的建立.数据的发送与接收和关闭已经建立的 Socket. 1 using System; 2 using System.Net; 3 using System.Windows; 4 using System.Windows.Controls; 5 using System.Windows.Documents

Linux下socket编程,附带tcp例子

1.网络中进程之间如何通信? 本地的进程间通信(IPC)有很多种方式,但可以总结为下面4类: 消息传递(管道.FIFO.消息队列) 同步(互斥量.条件变量.读写锁.文件和写记录锁.信号量) 共享内存(匿名的和具名的) 远程过程调用(Solaris门和Sun RPC) 但这些都不是本文的主题!我们要讨论的是网络中进程之间如何通信?首要解决的问题是如何唯一标识一个进程,否则通信无从谈起!在本地可以通过进程PID来唯一标识一个进程,但是在网络中这是行不通的.其实TCP/IP协议族已经帮我们解决了这个问

Linux下Socket编程

http://blog.chinaunix.net/uid-20733992-id-3450058.html 原文地址:Linux下Socket编程 作者:yulianliu1218 Linux下Socket编程 什么是Socket Socket接口是TCP/IP网络的API,Socket接口定义了许多函数或例程,程序员可以用它们来开发TCP/IP网络上的应用程序.要学Internet上的TCP/IP网络编程,必须理解Socket接口. Socket接口设计者最先是将接口放在Unix操作系统里面

LR杂记-用LoadRunner编写socket应用的测试脚本

LoadRunner提供了很好的对socket应用的支持,用户可以通过录制方法完全获得客户端发送和接收的数据,然后在录制的基础上对相应的数据进行参数化和关联等处理. 但在有些情况下(例如,客户端程序没有windows上的版本),我们就很难通过录制达成生成脚本的目标了.但如果我们能够完全知晓服务端和客户端的交互过程,完全手工编写一个测试脚本也并不是一件特别困难的事情. 在本文中,我们以一个实际的例子说明如何根据服务端和客户端交互的过程,用LoadRunner自行编写相应的脚本. 以下是服务端工作线

基于TCP的Socket通信

这里的例程跟前面"基于TCP的Socket"类似,前面是客户端给服务器端发信息,这里是服务器端给客户端发信息 TCP通信模式: TCP/IP通信协议是一种可靠的网络协议,它在通信的两端各建立一个Socket,从而在通信两端之间形成网络虚拟链路. 一旦建立了虚拟的网络链路,两端的程序就可以通过虚拟链路进行通信. Java使用Socket对象来代表两端的通信接口,并通过Socket产生I/O流来进行网络通信. SimpleServer.java  服务器程序,不需要建立Android项目,

Linux下socket编程基本知识

本文档主要讲解了Linux下socket编程的一些基本知识,主要包括套接字和字节序的概念,以及一些常用的结构体和函数. 本文是在网易云课堂学习过程中的记录,这个老师讲得很不错,推荐大家围观. Linux网络编程 Linux网络编程|人工智能物联网 1.概念 1.1套接字(socket) Socket(套接字)是一种通讯机制,它包含一整套的调用接口和数据结构的定义,它给应用进程提供了使用如TCP/UDP等网络协议进行网络通讯的手段. Linux中的网络编程通过socket接口实现,socket既是

HTTP,TCP,Socket

TCP/IP三次握手和HTTP过程 1.TCP连接 手机能够使用联网功能是因为手机底层实现了TCP/IP协议,可以使手机终端通过无线网络建立TCP连接.TCP协议可以对上层网络提供接口,使上层网络数据的传输建立在“无差别”的网络之上. 建立起一个TCP连接需要经过“三次握手”: 第一次握手:客户端发送syn包(syn=j)到服务器,并进入SYN_SEND状态,等待服务器确认: 第二次握手:服务器收到syn包,必须确认客户的SYN(ack=j+1),同时自己也发送一个SYN包(syn=k),即SY

TCP下的套接字编程

1.什么是套接字 应用层通过传输层进行数据通信时,TCP和UDP会遇到同时为多个应用程序进程提供并发服务的问题.多个TCP连接或多个应用程序进程可能需要通过同一个TCP协议端口传输数据.为了区别不同的应用程序进程和连接,许多计算机操作系统为应用程序与TCP/IP协议交互提供了称为套接字(Socket)的接口.区分不同应用程序进程间的网络通信和连接,主要有3个参数:通信的目的IP地址.使用的传输层协议(TCP或UDP)和使用的端口号.Socket原意是"插座".通过将这3个参数结合起来,