您的位置:首页 > 理论基础 > 计算机网络

Windows下使用TCP协议变长交互客户端和服务器的数据传输

2016-12-21 22:55 936 查看
之前有提及Windows下交互式服务器和客户端进行定长的数据传输,但是这样会存在浪费的情况,所以今天就上传以前课堂上学习过的变长数据传输。

其是在定长数据传输的基础上,双方发送的数据中不含了一个结构化的头部信息。如:

struct
{
unsigned int reclen;
char buf =[MAXLINE];
}packet;
跟前面的工程一样,服务器和客户端各自的工程中都包含着SocketFrame.h和SocketFrame.cpp这两个文件,我这里就不再写上去。主要就写服务器数据传输源码和客户端的数据传输源码。
服务器:

// EchoTCPServer.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include "SocketFrame.h"
#include "winsock2.h"
#define ECHOPORT "7210"
int tcp_server_fun_recvn( SOCKET s ,int flen);
int main(int argc, char* argv[])
{
CSocketFrame frame;
int iResult = 0;
SOCKET ListenSocket, ConnectSocket;
int nlen =0;
//输入参数合法性检查
if (argc != 2)
{
printf("usage: EchoTCPServer-recvn <定长接收长度>");
return -1;
}
//char *len =*argv[1];
nlen = atoi(argv[1]);
if ( nlen <= 0 )
{
printf("不正确的输入:<定长接收长度>!");
return -1;
}

//Windows Sockets Dll初始化
frame.start_up();

//创建服务器端的流式套接字并在指定端口号上监听
ListenSocket = frame.tcp_server( NULL, ECHOPORT );
if ( ListenSocket == -1 )
return -1;
printf("服务器准备好回射服务。。。\n");
for ( ; ; ) {
ConnectSocket = accept( ListenSocket, NULL, NULL );
if( ConnectSocket != INVALID_SOCKET ){
//建立连接成功
printf("\r\n建立连接成功\n\n");
//定长接收数据
iResult = tcp_server_fun_recvn( ConnectSocket,nlen);
//如果出错,关闭当前连接套接字,继续接收其它客户端的请求
if(iResult == -1)
printf("当前连接已关闭或出错!\n");
}
else{
printf("accept 函数调用错误,错误号: %d\n", WSAGetLastError());
frame.quit( ListenSocket );
return -1;
}

//关闭连接套接字
if ( closesocket( ConnectSocket ) == SOCKET_ERROR)
printf("closesocket 函数调用错误,错误号:%d\n", WSAGetLastError());;
}
frame.quit( ListenSocket );
return 0;
}
/********************************************************
函数名:tcp_server_fun_recvn
输入参数:SOCKET s:服务器的连接套接字
int flen:指定接收长度
输出参数:0:成功,-1:失败
功能:tcp_server:定长接收数据并统计字节数
********************************************************/
int tcp_server_fun_recvn( SOCKET s ,int flen)
{
CSocketFrame frame;
int iResult = 0;
char recvline[MAXLINE];
do {
memset( recvline, 0, MAXLINE );
//接收定长数据
iResult = frame.recvn( s, recvline, flen);
if (iResult > 0){
printf("服务器端接收到%d字节的数据:%s\n", iResult,recvline);
}
else{
if (iResult == 0)
printf("对方连接关闭,退出\n");
else{
printf("recv 函数调用错误,错误号: %d\n", WSAGetLastError());
iResult = -1;
}
}
} while (iResult > 0);
return iResult;
}



客户端:

// EchoTCPClient.cpp : 定义控制台应用程序的入口点。
//

#include "stdafx.h"

#include "SocketFrame.h"
int tcp_client_fun_recvn(FILE *fp,SOCKET s);
#define ECHOPORT "7210"
int main(int argc, char* argv[])
{
CSocketFrame frame;
int iResult;
SOCKET ClientSocket;

//输入参数合法性检查
if (argc != 2)
{
printf("usage: EchoTCPClient-recvn <IPaddress>");
return -1;
}

//Windows Sockets Dll初始化
frame.start_up();

//创建客户端的流式套接字,并与服务器建立连接
printf("连接建立成功,请输入回射字符串。。。\n");
ClientSocket = frame.tcp_client( ( char *)argv[1], ECHOPORT );
if ( ClientSocket == -1 )
return -1;

//开始回射请求的发送与接收
iResult = tcp_client_fun_recvn(stdin,ClientSocket);

frame.quit( ClientSocket );
return iResult;
return 0;
}

/********************************************************
函数名:tcp_client_fun_recvn
输入参数:FILE *fp:指向FILE类型的对象
SOCKET s:服务器的连接套接字
输出参数:0:成功,-1:失败
功能:测试服务器定长接收能力,根据用户输入,持续向服务器发送数据
*********************************************************/
int tcp_client_fun_recvn(FILE *fp,SOCKET s)
{
int iResult;
char sendline[MAXLINE],recvline[MAXLINE];
memset(sendline,0,MAXLINE);
memset(recvline,0,MAXLINE);

//循环发送用户的输入数据,并接收服务器返回的应答,直到用户输入"Q"结束
while(fgets(sendline,MAXLINE,fp)!=NULL)
{
if( *sendline == 'Q'){
printf("input end!\n");
// 数据发送结束,调用shutdown()函数声明不再发送数据,此时客户端仍可以接收数据
iResult = shutdown(s, SD_SEND);
if (iResult == SOCKET_ERROR) {
printf("shutdown failed with error: %d\n", WSAGetLastError());
}
return 0;
}
iResult = send(s,sendline,strlen(sendline),0);
if(iResult == SOCKET_ERROR)
{
printf("send 函数调用错误,错误号: %ld\n", WSAGetLastError());
return -1;
}
printf("\r\n客户端发送数据:%s\r\n", sendline);
memset(sendline,0,MAXLINE);
}
return iResult;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
相关文章推荐