好久不来写BLOG了,最近在写一个文件传送的程序,可是在发文件中使用fread去读取文件,如果定义的缓存不合适当时的网速就会出问题,设置过小,每次传送的文件就非常小,设置过大,在另一端写文件就可能没有完整的写完上步的内容,紧接着下一步内容就传过来。当然我们都不希望出现这样的结果。于是就写了一个测试网速的程序。
其实大体步骤就是一下:
WINSOCK C/S的建立过程:
服务器 客户端
________________________________________________
1 初始化WSA 1 初始化WSA
____________________________________________________
2 建立一个SOCKET 2 建立一个SOCKET
_____________________________________________________
3 绑定SOCKET 3 连接到服务器
_____________________________________________________
4 在指定的端口监听 4 发送和接受数据
_____________________________________________________
5 接受一个连接 5 断开连接
______________________________________________________-
6 发送和接受数据
___________________________________________________
7 断开连接
__________________________________________________
我是一个新手,当然存在很多不晓得的知识,也遇到了不少问题,下面我就我遇到的问题概括一下:
1,初始化WSA。以前从未接触过SOCKET传文件,一看见初始化,不就是要定义么?所以就在网上找了半天,什么也没找到,后来经我哥解释,方才知晓,原来#include “winsock.h”中已经涵盖了WSA 信息,无非就是
int nRet;
//初始化
WSADATA wsaData;
nRet = WSAStartup(514, &wsaData);//wsaData用来存储系统传回的关于WINSOCK的资料
if (nRet != 0)
{
printf("WSAStartup error!/n");//返回值不等于0,说明初始化失败
return 0;
}网上现成的,当然一开始我也找到了,可是开始时就是不知道为什么要这样就是初始化。毕竟是新手么。
2,建立一个SOCKET。
//建立SOCKET结构
SOCKET m_socket;//建立一个m_socket的SOCKET句柄
m_socket = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP); //创建TCP协议,返回值保存在m_socket中
//以下代码用于检查返回值是否有错误
if(m_socket == INVALID_SOCKET)
{
printf("Error at socket():%d/n",GetLastError());
WSACleanup(); //释放资源
return 1; //如果socket()调用失败,他将返回INVALID_SOCKET
} //应用程序在完成对请求的SOCKET库使用后,要调用WSACleanup函数来结束SOCKET库的绑定,并且释放资源.
这一步倒还是能大概了解一下,也都能看的懂。
3,绑定SOCKET。就是使用bind函数进行操作,这一步就是要绑定我们的IP。当然服务端和客户端都要使用服务端的IP。我这用了一个自动获得IP的函数(内网和外网的都能获得)。在IP这我想说几句,我们如果使用路由器上网,我们所用的IP就有两种,一个是针对外网的IP,一个是针对路由器内用户的IP。我是使用路由器上网的,但是发现目前自己的程序还是不能测试A路由器中的用户和B路由器中用户之间的网速。起码我目前是做不到,还请看到帖子的同志们能给详细的介绍个好方法。
4 ,在指定的端口监听。当绑定完成后,服务器必须建立一个监听队列,以接受客户端的请求。listen()使服务器进入监听状态,该函数调用成功返回0,否则返回 。一旦服务器开始监听,我们就要指定一个句柄来表示利用ACCEPT()函数接受的连接,这个句柄是用来发送和接受数据的表示。还需建立一个SOCKET句柄 。Socket AcceptSocket 然后利用无限循环来检测是否有连接传入。
5, 接受一个连接。一但有连接请求,ACCEPT()函数就会被调用,并且返回这次连接的句柄.。
SOCKET AcceptSocket;
AcceptSocket = SOCKET_ERROR;
while(AcceptSocket==SOCKET_ERROR)
{
AcceptSocket=accept(m_socket,NULL,NULL);
printf("Get connect!/n");
break;
}
SOCKET m_server;
m_server = AcceptSocket;
6,发送和接受数据。在控制台里用ping测试响应时间是计算机使用的是32字节,所以我们就定义一个32字节长度的字符串,并申请两个长度为33的缓存,并将字符串放到其中一个缓存内,传送数据中,我们使用的是5次循环,在服务端用GetTickCount()获得当前的CPU转数,一次循环后再调用函数GetTickCount()获得一次转数,两者之差即为一次传送中CPU转过的圈数,也就对应了一个传送32位的时间,最后得到5次循环的平均值。客户端使用的是死循环,并且把接收到的数据重新send到服务端,并和服务端的缓存strcmp(),如果是为0就代表客户端返回正确,也就是一次循环成功,但是网络中有可能断线,此时我采用的处理方法是:发送成功时recv的返回值是字符串的长度,失败则是返回-1,于是我就使用DWORD dwerror = WSAGetLastError ()获得dwerror,如果其值为0x2746,则表示网络出问题,我们就跳出循环,重新检测。客户端也可以使用同样的方法进行判断网络问题,当然客户端还要使用recv函数的返回值退出死循环,条件就是recv返回值为0,也就是接受不到任何数据。我们得到了传送32位字节的平均时间也就能得到每秒能传送多少字节了。
7, 断开连接。释放缓存free,释放端口closesocket。最后 WSACleanup()。
对此函数感兴趣的话,请到本人自愿下载。