回射程序3(服务器)——客户服务器不定长接收数据
来源:互联网 发布:360驱动大师mac版 编辑:程序博客网 时间:2024/05/17 04:46
设计思路上一篇已经说明。
贴上服务器的代码:
// 回显服务器3.cpp : 定义控制台应用程序的入口点。//#include "stdafx.h"#include <stdio.h>#include <stdlib.h>#include <winsock2.h>#include <string.h>#pragma comment(lib,"wsock32.lib")#define SERVERPROT 6000#define MAXSIZE 100//函数声明int recvn(SOCKET s, char * recvbuf, unsigned int fixedlen);int recvvl(SOCKET s, char * recvbuf, unsigned int recvbuflen);int _tmain(int argc, _TCHAR* argv[]){//初始化WinSockWSADATA wsaData;int ret = WSAStartup(MAKEWORD(2,2),&wsaData);if(ret!=0){printf("WSAStartup() failed!code:%d\n",WSAGetLastError());return -1;}if(LOBYTE(wsaData.wVersion)!=2||HIBYTE(wsaData.wVersion)!=2){WSACleanup();printf("Invalid WinSock Version\n");return -1;}//创建监听套接字SOCKET slisten;slisten = socket(AF_INET,SOCK_STREAM,0);if(slisten == INVALID_SOCKET){printf("socket() failed!code:%d\n",WSAGetLastError());WSACleanup();return -1;}//构建服务器本地地址信息struct sockaddr_in serveraddr;serveraddr.sin_family = AF_INET;serveraddr.sin_port = htons(SERVERPROT);serveraddr.sin_addr.S_un.S_addr = INADDR_ANY;//绑定ret = bind(slisten,(sockaddr*)&serveraddr,sizeof(serveraddr));if(ret == SOCKET_ERROR){printf("bind() failed!code:%d\n",WSAGetLastError());closesocket(slisten);WSACleanup();return -1;}//侦听连接请求ret = listen(slisten,5);if(ret == SOCKET_ERROR){printf("listen() failed!code:%d\n",WSAGetLastError());closesocket(slisten);WSACleanup();return -1;}printf("waiting for client connecting...\n");//接收客户端连接struct sockaddr_in clientaddr;int clientaddrlen = sizeof(clientaddr);SOCKET sServer;//连接套接字char buff[MAXSIZE];//接收缓存char sendbuf[MAXSIZE];//发送缓存unsigned int slen=0; //发送数据长度unsigned int buflen=MAXSIZE;sServer = accept(slisten,(struct sockaddr*)&clientaddr,&clientaddrlen);if(sServer == INVALID_SOCKET){printf("accept() failed!code:%d\n",WSAGetLastError());closesocket(slisten);WSACleanup();return -1;}while(TRUE) //循环接收数据{memset(buff, 0 , MAXSIZE);memset(sendbuf,0,MAXSIZE);ret = recvvl(sServer,buff,buflen);if(ret==SOCKET_ERROR){int nErrCode = WSAGetLastError();//错误代码if (WSAENOTCONN == nErrCode){printf("The socket is not connected!\n");}else if(WSAESHUTDOWN == nErrCode){printf("The socket has been shut down!\n");}else if (WSAETIMEDOUT == nErrCode){printf("The connection has been dropped!\n");}else if (WSAECONNRESET == nErrCode){printf("The virtual circuit was reset by the remote side!\n");}else{}closesocket(sServer);closesocket(slisten);WSACleanup();return -1;}sprintf(sendbuf,"echo:%s",buff);printf("%s\n",sendbuf);slen = (unsigned int)strlen(sendbuf);slen = htonl(slen);ret = send(sServer,(char*)&slen,sizeof(unsigned int),0);if (SOCKET_ERROR == ret){int nErrCode = WSAGetLastError();//错误代码if (WSAENOTCONN == nErrCode){printf("The socket is not connected!\n");}else if(WSAESHUTDOWN == nErrCode){printf("The socket has been shut down!\n");}else if (WSAETIMEDOUT == nErrCode){printf("The connection has been dropped!\n");}else{}closesocket(sServer);closesocket(slisten);WSACleanup();return -1;}ret = send(sServer,sendbuf,strlen(sendbuf),0);if (SOCKET_ERROR == ret){int nErrCode = WSAGetLastError();//错误代码if (WSAENOTCONN == nErrCode){printf("The socket is not connected!\n");}else if(WSAESHUTDOWN == nErrCode){printf("The socket has been shut down!\n");}else if (WSAETIMEDOUT == nErrCode){printf("The connection has been dropped!\n");}else{}closesocket(sServer);closesocket(slisten);WSACleanup();return -1;}}closesocket(sServer);closesocket(slisten);WSACleanup();return 0;}//指定长度接收int recvn(SOCKET s, char * recvbuf, unsigned int fixedlen){int iResult; //存储单次recv操作的返回值int cnt; //用于统计相对于固定长度,剩余多少字节尚未接收cnt = fixedlen;while ( cnt > 0 ) {iResult = recv(s, recvbuf, cnt, 0);if ( iResult < 0 ){//数据接收出现错误,返回失败printf("接收发生错误: %d\n", WSAGetLastError());return -1;}if ( iResult == 0 ){//对方关闭连接,返回已接收到的小于fixedlen的字节数printf("连接关闭\n");return fixedlen - cnt;}//printf("接收到的字节数: %d\n", iResult);//接收缓存指针向后移动recvbuf +=iResult;//更新cnt值cnt -=iResult; }return fixedlen;}int recvvl(SOCKET s, char * recvbuf, unsigned int recvbuflen){int iResult;//存储单次recvn操作的返回值unsigned int reclen; //用于存储报文头部存储的长度信息//获取接收报文长度信息iResult = recvn(s, ( char * )&reclen, sizeof( unsigned int ));if ( iResult !=sizeof ( unsigned int ) ){//如果长度字段在接收时没有返回一个整型数据就返回(连接关闭)或-1(发生错误)if ( iResult == -1 ) {printf("接收发生错误: %d\n", WSAGetLastError());return -1;}else {printf("连接关闭\n");return 0;}}//转换网络字节顺序到主机字节顺序reclen = ntohl( reclen );if ( reclen > recvbuflen ){printf("reclen>recvbuflen: %d>%d\n",reclen,recvbuflen);//如果recvbuf没有足够的空间存储变长消息,则接收该消息并丢弃,返回错误while ( reclen > 0){iResult = recvn( s, recvbuf, recvbuflen );if ( iResult != recvbuflen ) {//如果变长消息在接收时没有返回足够的数据就返回(连接关闭)或-1(发生错误)if ( iResult == -1 ) {printf("接收发生错误: %d\n", WSAGetLastError());return -1;}else {printf("连接关闭\n");return 0;}}reclen -= recvbuflen;//处理最后一段数据长度if ( reclen < recvbuflen )recvbuflen = reclen;}printf("可变长度的消息超出预分配的接收缓存\r\n");return -1;}//接收可变长消息iResult = recvn( s, recvbuf, reclen );if ( iResult != reclen ){//如果消息在接收时没有返回足够的数据就返回(连接关闭)或-1(发生错误)if ( iResult == -1 ) {printf("接收发生错误: %d\n", WSAGetLastError());return -1;}else {printf("连接关闭\n");return 0;}}return iResult;}
0 0
- 回射程序3(服务器)——客户服务器不定长接收数据
- 回射程序3(客户端)——客户服务器不定长接收数据
- 回射程序(服务器)——客户接收一行数据
- 回射程序2(服务器)——服务器接收定长数据
- 回射程序(客户端)——客户接收一行数据
- tcp客户/服务器回射程序之三-----数据格式
- tcp客户/服务器回射程序之二-----处理SIGCHILD信号
- tcp客户/服务器回射程序之四-----select函数的使用
- STM32接收不定长数据
- tcp客户/服务器回射程序之五-----用shutdown函数解决在批量方式下所引起的问题
- 《unix网络编程》(18)基本UDP套接字 简单客户服务器回射程序及改进
- linux客户端服务器回射程序-编程记录
- Stm32——串口空闲中断+DMA接收不定长数据
- UNIX网络编程之第二步之嚼烂基本TCP套接字编程(以简单的TCP客户/服务器回射程序为例)
- 客户—服务器框架基础
- STM32F207运用串口空闲中断+DMA接收不定长数据
- STM32F207运用串口空闲中断+DMA接收不定长数据
- STM32串口接收不定长数据原理与源程序
- 详解java匿名内部类
- ubuntu下terminal快捷键
- Eclipse 代码提示功能失效问题
- PHP CURL 使用代理访问服务器
- SDK Manager更新SDK和API的方法,好不容易找到的正解!!
- 回射程序3(服务器)——客户服务器不定长接收数据
- 黑马程序员-Java编程基础
- Android ArrayAdapter 使用思路
- LINUX内核中的xx_initcall初始化标号
- 归并排序
- 需求分析阶段的工作(一):业务用例和系统用例
- 设计模式六大原则(6):开闭原则
- sqlserver数据导入mysql五:多线程导数据脚本(读取前面拆分的表名进行数据导入)
- Delphi 关键字详解