TCP协议的问题

Server端接收到Client端信息后不会返回给Client端

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

#include "stdafx.h"
#include <Windows.h>
#include <WinSock2.h>
#include <strsafe.h>

#pragma comment(lib, "Ws2_32.lib")

#define GRS_ALLOC(sz) HeapAlloc(GetProcessHeap(), 0 ,sz)
#define GRS_CALLOC(sz) HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, sz)
#define GRS_CREALLOC(p, sz) HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, p, sz)
#define GRS_SAFEFREE(p) if(NULL != p){HeapFree(GetProcessHeap(), 0, p); p = NULL;}

#define GRS_USEPRINTF() TCHAR pBuf[1024] = {}; char pBufA[1024] = {};
#define GRS_PRINTF(...)\
 StringCchPrintf(pBuf, 1024, __VA_ARGS__);\
 WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), pBuf, lstrlen(pBuf), NULL, NULL);
#define GRS_PRINTFA(...)\
 StringCchPrintfA(pBufA, 1024, __VA_ARGS__);\
 WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), pBufA, lstrlenA(pBufA), NULL, NULL);

#define SOCK_VERH 2
#define SOCK_VERL 2
#define GRS_SERVER_PORT 5634
int _tmain(int argc, _TCHAR* argv[])
{
 GRS_USEPRINTF();
 WORD wVer = MAKEWORD(SOCK_VERH, SOCK_VERL);
 WSADATA wd;
 int err = ::WSAStartup(wVer, &wd); //因为多个WinSock版本库可能共存于一个系统,所以应用程序必须明确指定加载合适的WinSock版本库,这个过程称为WinSock初始化,一般用WSAStartup
 //高字节副版本号,低字节主版本号
 if(0 != err)
 {
  GRS_PRINTF(_T("无法初始化Scoket2环境,错误码为:%d!\n"), WSAGetLastError());
  return 1;
 }
 if(LOBYTE(wd.wVersion) != SOCK_VERH || HIBYTE(wd.wVersion) != SOCK_VERL)
 {
  GRS_PRINTF(_T("无法初始化%d.%d版本环境!\n"), SOCK_VERH, SOCK_VERL);
  ::WSACleanup();
  return 2;
 }
 GRS_PRINTF(_T("WinSock库初始化成功!\n\t当前系统中支持最高的WinSock版本为%d.%d\n\t当前应用程序使用的WinSock版本为%d.%d\n"),
  LOBYTE(wd.wHighVersion), HIBYTE(wd.wHighVersion),
  LOBYTE(wd.wVersion), HIBYTE(wd.wVersion));

SOCKET skServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
 SOCKET skClient = INVALID_SOCKET;
 SOCKADDR_IN saClient = {};
 int isaLen = sizeof(SOCKADDR_IN);
 VOID* pskBuf = NULL;
 VOID* pskBufTmp = NULL;
 int iBufLen = 1024;
 int iBufLenTmp = 0;
 int iRecv = 0;

SOCKADDR_IN sa = {AF_INET};
 sa.sin_addr.s_addr = htonl(INADDR_ANY);
 sa.sin_port = htons(GRS_SERVER_PORT);

if(0 != bind(skServer, (SOCKADDR*)&sa, sizeof(SOCKADDR_IN)))
 {
  GRS_PRINTF(_T("绑定到指定端口出错!\n"));
  goto CLEAN_UP;
 }
 if(0 != listen(skServer, SOMAXCONN))
 {
  GRS_PRINTF(_T("SOCKET进入监听模式出错!\n"));
  goto CLEAN_UP;
 }
 while(INVALID_SOCKET != (skClient=accept(skServer, (SOCKADDR*)&saClient, &isaLen)))
 {
  GRS_PRINTFA("客户端[%s : %u]连接进来了.....\n", inet_ntoa(saClient.sin_addr), ntohs(saClient.sin_port));
  GRS_PRINTF(_T("\t开始接受客户端数据......\n"));
  pskBuf = GRS_CALLOC(iBufLen);
  pskBufTmp = pskBuf;
  do
  {
   iRecv = recv(skClient, (char*)pskBufTmp, iBufLen-iBufLenTmp, 0);
   if(SOCKET_ERROR == iRecv || 0 == iRecv)
   {
    break;
   }
   if(iRecv >= (iBufLen - iBufLenTmp))
   {
    iBufLenTmp = iBufLen;
    iBufLen += 1024;
    pskBuf = GRS_CREALLOC(pskBuf, iBufLen);
    pskBufTmp = (void*)((BYTE*)pskBuf + iBufLenTmp);
    continue;
   }
  }
  while (1);
  
  if(SOCKET_ERROR != iRecv && 0 != iRecv)
  {
   GRS_PRINTF(_T("\t接收客户端数据成功,开始返回......\n"));
   send(skClient, (const char*)pskBuf, iBufLen, 0);
  }
  else
  {
   GRS_PRINTF(_T("\t接收客户端数据失败,关闭连接......\n"));
  }

GRS_SAFEFREE(pskBuf);
  pskBufTmp = NULL;
  iBufLenTmp = 0;
  iBufLen = 1024;

shutdown(skClient, SD_BOTH);
  closesocket(skClient);
 }

CLEAN_UP:
 _tsystem(_T("PASUE"));
 if(INVALID_SOCKET != skServer)
 {
  closesocket(skServer);
 }
 ::WSACleanup();

return 0;
}               //Server端的代码

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

#include "stdafx.h"
#include <Windows.h>
#include <strsafe.h>
#include <WinSock2.h>

#pragma comment(lib, "Ws2_32.lib")

#define GRS_ALLOC(sz) HeapAlloc(GetProcessHeap(), 0 ,sz)
#define GRS_CALLOC(sz) HeapAlloc(GetProcessheap(), HEAP_ZERO_MEMORY, sz)
#define GRS_CREALLOC(p, sz) HeapReAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, p, sz)
#define GRS_SAFEFREE(p) if(NULL != p){HeapFree(GetProcessHeap(), 0, p); p = NULL;}

#define GRS_USEPRINTF() TCHAR pBuf[1024] = {}; char pBufA[1024] = {};
#define GRS_PRINTF(...)\
 StringCchPrintf(pBuf, 1024, __VA_ARGS__);\
 WriteConsole(GetStdHandle(STD_OUTPUT_HANDLE), pBuf, lstrlen(pBuf), NULL, NULL);
#define GRS_PRINTFA(...)\
 StringCchPrintfA(pBufA, 1024, __VA_ARGS__);\
 WriteConsoleA(GetStdHandle(STD_OUTPUT_HANDLE), pBufA, lstrlenA(pBufA), NULL, NULL);

#define SOCK_VERH 2
#define SOCK_VERL 2
#define GRS_SERVER_PORT 5634

int _tmain(int argc, _TCHAR* argv[])
{
 GRS_USEPRINTF();
 WORD wVer = MAKEWORD(SOCK_VERH, SOCK_VERL);
 WSADATA wd;
 int err = ::WSAStartup(wVer, &wd); //因为多个WinSock版本库可能共存于一个系统,所以应用程序必须明确指定加载合适的WinSock版本库,这个过程称为WinSock初始化,一般用WSAStartup
 //高字节副版本号,低字节主版本号
 if(0 != err)
 {
  GRS_PRINTF(_T("无法初始化Scoket2环境,错误码为:%d!\n"), WSAGetLastError());
  return 1;
 }
 if(LOBYTE(wd.wVersion) != SOCK_VERH || HIBYTE(wd.wVersion) != SOCK_VERL)
 {
  GRS_PRINTF(_T("无法初始化%d.%d版本环境!\n"), SOCK_VERH, SOCK_VERL);
  ::WSACleanup();
  return 2;
 }
 GRS_PRINTF(_T("WinSock库初始化成功!\n\t当前系统中支持最高的WinSock版本为%d.%d\n\t当前应用程序使用的WinSock版本为%d.%d\n"),
  LOBYTE(wd.wHighVersion), HIBYTE(wd.wHighVersion),
  LOBYTE(wd.wVersion), HIBYTE(wd.wVersion));

SOCKET skClient = socket(AF_INET, SOCK_STREAM, IPPROTO_IP);
 SOCKADDR_IN sa = {AF_INET};
 sa.sin_addr.s_addr = inet_addr("127.0.0.1");
 sa.sin_port = htons(GRS_SERVER_PORT);
 WCHAR pszSendMsg[] = _T("Hello Internetssssssssssssssssssssssssss!");
 size_t szLen = 0;
 StringCchLength(pszSendMsg, 30, &szLen);
 WCHAR pszRecvBuf[1024] = {};
 if(0 != connect(skClient, (SOCKADDR*)&sa, sizeof(SOCKADDR_IN)))
 {
  GRS_PRINTF(_T("连接服务器出错......\n"));
  goto CLEAN_UP;
 }
 send(skClient, (char*)pszSendMsg, szLen * sizeof(WCHAR), 0);
 recv(skClient, (char*)pszRecvBuf, 1024 * sizeof(WCHAR), 0);
 GRS_PRINTF(_T("ECHO:%s\n"), pszRecvBuf);

CLEAN_UP:
 if(INVALID_SOCKET != skClient)
 {
  shutdown(skClient, SD_BOTH);
  closesocket(skClient);
 }
 _tsystem(_T("PASUE"));
 ::WSACleanup();
 return 0;
}  //Client端的代码

Server端接收到Client端信息后不会返回给Client端,

时间: 2024-10-11 04:36:27

TCP协议的问题的相关文章

tcp协议分析

tcp协议解析 TCP在网络OSI的七层模型中的第四层--Transport层,IP在第三层--Network层,ARP在第二层--Data Link层.在第二层上的数据,我们叫Frame,在第三层上的数据叫Packet,第四层的数据叫Segment. 我们程序的数据首先会打到TCP的Segment中,然后TCP的Segment会打到IP的Packet中,然后再打到以太网Ethernet的Frame中,传到对端后,各个层解析自己的协议,然后把数据交给更高层的协议处理 TCP头格式 TCP数据段格

时间获取程序服务器 TCP 协议相关性

本文为senlie原创,转载请保留此地址:http://blog.csdn.net/zhengsenlie 最初代码: 这是一个简单的时间获取服务器程序.它和时间获取程序客户端一道工作. TCP/IPv4, IPv6 协议相关 IPv4 --> IPv6 (把代码中出现的左边的字符串换为右边的,就变成了IPv6版本的) sockaddr_in --> sockaddr_in6 AF_INET --> AF_INET6 sin_family --> sin6_family sin_p

TCP 协议难点汇总

本文不会完整的介绍TCP,只有在涉及到的时候随便提一下.不适合对TCP整个流程和框架没有了解过的人阅读. 1  TCP 四次挥手中的TIME_WAIT状态的意义何在. 下图四次挥手的一个大体的流程 我们发现在A发送完一个最后一个ACK后,B一收到这个ACK就证明关闭请求已经被确认了,所以可以直接关闭.但是这时候A怎么知道这个ACK是否已经到达了对端呢?这个时候为了保证双方能够正常关闭,就引入了一个MSL时间,MSL定义 "一个电磁波信号在地球最大的存活时间 " . 所以该ACK存活一个

利用TCP协议实现通信

Socket的TCP通讯 一. socket的通讯原理 服务器端的步骤如下. (1)建立服务器端的Socket,开始侦听整个网络中的连接请求. (2)当检测到来自客户端的连接请求时,向客户端发送收到连接请求的信息,并建立与客户端之间的连接. (3)当完成通信后,服务器关闭与客户端的Socket连接. 客户端的步骤如下. (1)建立客户端的Socket,确定要连接的服务器的主机名和端口. (2)发送连接请求到服务器,并等待服务器的回馈信息. (3)连接成功后,与服务器进行数据的交互. (4)数据处

浅析TCP协议与UDP协议

TCP(Transmission Control Protocol),全称传输控制协议.工作在TCP/IP协议栈中的传输层,为主机层对主机层的连接提供了可靠的链接服务.此协议通过三个步骤使客户机与服务器建立一个连接,并通过四个步骤关闭此连接,这个过程我们分别称之为三次握手和四次挥手. UDP((User Datagram Protocol),全称用户数据报协议.同样工作在传输层,是一种非面向连接的协议,因为其无恢复数据功能,所以是一种不可靠的网络访问.但因为发送数据时无需向TCP一样反复建立连接

TCP协议

TCP(Transmission Control Protocol )传输控制协议,是目前传输层应用最广泛的协议,当然这跟它的特性息息相关. 一.它的主要特性有: 1.可靠,面向连接 2.工作在传输层面向连接协议 3.全双工协议 4.半关闭(单方关闭) 5.错误检查 每个数据包有编号,对方收到之后,会告诉发送方收到了,回给对方说我下次希望收到第n+1个包,假如发送了三个包,但是接受方只收到了两个,会说下次希望收到第三个包,那么就实现了错误检查和重传 6.将数据打包成段,排序 即标记序列号,有时候

TCP协议中的三次握手和四次挥手(图解)【转】

建立TCP需要三次握手才能建立,而断开连接则需要四次握手.整个过程如下图所示: 先来看看如何建立连接的. [更新于2017.01.04 ]该部分内容配图有误,请大家见谅,正确的配图如下,错误配图也不删了,大家可以比较下,对比理解效果更好.这么久才来更新,抱歉!! 错误配图如下: 首先Client端发送连接请求报文,Server段接受连接后回复ACK报文,并为这次连接分配资源.Client端接收到ACK报文后也向Server段发生ACK报文,并分配资源,这样TCP连接就建立了. 那如何断开连接呢?

TCP协议疑难杂症全景解析

说明: 1).本文以TCP的发展历程解析容易引起混淆,误会的方方面面2).本文不会贴大量的源码,大多数是以文字形式描述,我相信文字看起来是要比代码更轻松的3).针对对象:对TCP已经有了全面了解的人.因为本文不会解析TCP头里面的每一个字段或者3次握手的细节,也不会解释慢启动和快速重传的定义4).除了<TCP/IP详解>(卷一,卷二)以及<Unix网络编程>以及Linux源代码之外,学习网络更好的资源是RFC 5).本文给出一个提纲,如果想了解细节,请直接查阅RFC 6).翻来覆去

TCP协议的三次握手和四次挥手

暂时需要的信息有: ACK : TCP协议规定,只有ACK=1时有效,也规定连接建立后所有发送的报文的ACK必须为1 SYN(SYNchronization) : 在连接建立时用来同步序号.当SYN=1而ACK=0时,表明这是一个连接请求报文.对方若同意建立连接,则应在响应报文中使SYN=1和ACK=1. 因此,  SYN置1就表示这是一个连接请求或连接接受报文. FIN (finis)即完,终结的意思, 用来释放一个连接.当 FIN = 1 时,表明此报文段的发送方的数据已经发送完毕,并要求释

TCP协议中的标志位

TCP/IP协议通常放在一起来说,但是它们是两个不同的协议,所起的作用也不一样. IP协议是用来查找地址的,对应于网际互联层. TCP协议是用来规范传输规则的,对应着传输层. IP协议只负责找到地址,具体传输的工作交给TCP来完成. TCP在传输之前会进行三次沟通,一般称为“三握手”:传输数据断开的时候需要进行四次沟通,一般称为“四挥手”. 要理解这个过程首先需要理解TCP中的两个序号和三个标志位的含义: seq:sequence number的缩写,表示所传数据的序号.TCP传输时每一个字节都