- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
echo_server 和 echo_client 的代码贴在下面。我注意到当我在 echo_client 中输入超过一定长度的消息时,服务器会截断它的末尾并仅回显它的一部分。缓冲区大小为 1024 字节,我输入的消息比该长度短得多。这里发生了什么?我该如何解决这个问题,以便服务器回显在长度限制内提供的完整消息?
服务器代码:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <string.h>
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <winsock2.h>
#include <ws2tcpip.h>
#pragma comment(lib, "ws2_32.lib")
using namespace std;
static int MAXPENDING = 5;
int main(int argc, char *argv[])
{
WSADATA wsaData;
int iResult;
int optv = 0;
bool connected = false;
char *optval = (char*)&optv;
int optlen = sizeof(optval);
string Q = "quit";
const char *exit =Q.c_str();
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != NO_ERROR) {
wprintf(L"WSAStartup function failed with error: %d\n", iResult);
return 1;
}
if(argc!=2){
printf("Error: incorrect number of arguments. ");
return 1;
}
SOCKET servSock;
servSock = socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);
if(servSock==INVALID_SOCKET){
printf("Socket function failed with error: %d\n",GetLastError());
return 1;
}
u_int servPort = atoi(argv[1]);
sockaddr_in servAddr;
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(servPort);
int opt = setsockopt(servSock,SOL_SOCKET,SO_REUSEADDR,optval,sizeof(optval));
if(bind(servSock,(sockaddr*)&servAddr,sizeof(servAddr))<0){
printf("Bind function failed with error: %d\n", GetLastError());
return 1;
}
for(;;){
if(listen(servSock,MAXPENDING) < 0){
printf("Listen function failed with error: %d/n",GetLastError());
return 1;
}else{
char *str = new char[5];
printf("Server listening on port %d\n",servPort);
}
SOCKET clientSock;
sockaddr_in clientAddr;
socklen_t caddrlen = sizeof(clientAddr);
clientSock = accept(servSock,(sockaddr*)&clientAddr,&caddrlen);
if(clientSock < 0){
printf("Accept() function failed with error: %d/n", GetLastError());
goto QUIT;
}else if(clientSock >=0){
connected = true;
}
char cName[INET_ADDRSTRLEN];
if(inet_ntop(AF_INET,&clientAddr.sin_addr,cName,sizeof(cName))!=NULL){
printf("Handling client %s/%d\n", cName,ntohs(clientAddr.sin_port));
}else{
printf("Error: Unable to get client address");
}
char buffer[1024];
while(connected==true){
long nbytesrcvd = recv(clientSock,buffer,sizeof(buffer),0);
if(nbytesrcvd==0){
connected = false;
cout << endl;
cout << cName << ": client disconnected" << endl;
cout << endl;
break;
}
if(nbytesrcvd < 0){
printf("Error: recv() failed");
cout << endl;
goto QUIT;
}
if(nbytesrcvd > 0){
long nbytessent = send(clientSock,buffer,nbytesrcvd,0);
if(nbytessent < 0){
cout << "Error: send() failed" << endl;
cout << endl;
goto QUIT;
}else if(nbytessent!=nbytesrcvd){
cout << "send() error: sent unexpected # of bytes" << endl;
cout << endl;
goto QUIT;
}
}
}
QUIT:
int iResult = closesocket(clientSock);
if (iResult == SOCKET_ERROR) {
printf("closesocket function failed with error: %d\n",GetLastError());
}
}
}
和客户端代码:
#include "stdafx.h"
#include <iostream>
#include <string>
#include <string.h>
#ifndef UNICODE
#define UNICODE
#endif
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#define BUFFSIZE 1024
#pragma comment(lib, "ws2_32.lib")
using namespace std;
int main(int argc,char* argv[])
{
WSADATA wsaData;
int result;
bool connected = false;
hostent *rhost;
char buffer[BUFFSIZE];
string Q = "quit";
const char *exit =Q.c_str();
result = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (result != NO_ERROR) {
printf("WSAStartup function failed with error: %d\n", result);
return 1;
}
SOCKET connector;
connector = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (connector == INVALID_SOCKET) {
wprintf(L"socket function failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
string hname;
cout << "Enter host name(URL): ";
cin >> hname;
cout << endl;
string portnum;
cout << "Enter the port number you wish to connect on: " ;
cin >> portnum;
cout << endl;
char *hostname = const_cast<char*>(hname.c_str());
char *hostPort = const_cast<char*>(portnum.c_str());
rhost = gethostbyname(hostname);
in_addr addr;
addr.s_addr = *(u_long *)rhost->h_addr_list[0];
sockaddr_in clientserv;
clientserv.sin_family = AF_INET;
clientserv.sin_addr.s_addr = addr.s_addr;
clientserv.sin_port = htons(atoi(hostPort));
if(connect(connector,(sockaddr*)&clientserv,sizeof(clientserv))==SOCKET_ERROR){
printf("connect function failed with error: %d\n", GetLastError());
if(closesocket(connector)<0){
printf("closesocket function failed %d\n", GetLastError());
}
return 1;
}else{
connected = true;
cout << "Connected to host " << hname << " on port " << portnum << endl;
cout << "Type 'quit' to exit the program " << endl;
}
while(connected==true){
int nbr = 0;
string msg;
cout << ">";
getline(cin,msg);
cout << endl;
if(msg=="quit"){
connected = false;
goto quit;
}
int len = sizeof(msg);
const char *message = msg.c_str();
strncpy_s(buffer,message,sizeof(msg));
long nbs = send(connector,buffer,len,0);
if(nbs < 0){
printf("send() failed", GetLastError());
return 1;
}
while(nbr < nbs){
nbr = recv(connector,buffer,len,0);
if(nbr < 0){
printf("recv() failed", GetLastError());
return 1;
}else if(nbr==0){
printf("recv() failed: connection closed prematurely", GetLastError());
return 1;
}else if(nbr > 0){
string str(buffer);
cout << ">> " << str << endl;
cout << endl;
}
}
}
quit:
if (closesocket(connector) == SOCKET_ERROR) {
printf("closesocket function failed with error: %ld\n", GetLastError());
WSACleanup();
return 1;
}
WSACleanup();
return 0;
最佳答案
请记住,recv
可能不会一次接收到所有数据。这意味着服务器中的 recv
调用可能无法获得完整的消息,但会发回它获得的消息,而客户端可能只会收到从服务器发送的消息的一部分。
这不会有问题,除非您在客户端中只收到一次,然后继续做其他事情。就像你一样。
有两种解决方法:
制定一个简单的协议(protocol),要么在每条消息前加上消息长度,要么有一个特殊的消息结束标记。在第一种情况下,您将始终知道有多少数据并且可以在循环中读取,直到收到所有数据;在第二种情况下,您将在循环中接收,直到获得消息结束标记。
使套接字成为非阻塞的,并循环读取直到recv
返回错误,错误为WSAEWOULDBLOCK
。那么就没有更多的数据可以读取了。
客户端的错误:
int len = sizeof(msg);
此行返回字符串对象 的大小,而不是包含在对象中的字符串。您应该使用 msg.length()
来获取长度。您可以在几个地方使用它。
如果使用得当,使用 std::string
是完全没问题的。例如:
long nbs = send(connector, msg.c_str(), msg.length(), 0);
另一件事:
nbr = recv(connector, buffer, len, 0);
您在这里再次使用了错误的大小,该大小是由先前错误地使用 sizeof(msg)
提供的。相反,您应该提供实际缓冲区的大小。由于 buffer
是一个合适的数组,您可以使用例如sizeof(buffer) - 1
这里。 -1
是因为你从客户端发送的数据不是以零结尾的字符串,所以你需要在接收到的数据中预留一个空格来像字符串一样结束:
buffer[nbr] = '\0';
关于c++ - 使用套接字 send()/recv()(winsock) 回显服务器/客户端消息截断,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/16376979/
我想在一些计算机之间建立点对点连接,这样用户就可以在没有外部服务器的情况下聊天和交换文件。我的第一个想法如下: 我在服务器上创建了一个中央 ServerSocket,所有应用程序都可以连接到该服务器。
我正在 Unity 中构建多人游戏。为此,我必须将一些值从客户端发送到两个或多个通过服务器连接的客户端。我想将其构建为服务器真实游戏。客户端将使用 Android,他们的数据将通过服务器同步(可能是一
练习 C 网络编程:我正在编写一个简单的 TCP 客户端-服务器应用程序,它应该将消息(在每个客户端的单独线程中)作为字符串从服务器发送到客户端并在客户端(稍后将成为控制台商店应用程序)。我首先发送消
我使用证书身份验证设置了 AWS Client VPN。我正在为客户端-客户端访问系统进行设置,基本上如 this AWS scenario/example 中所述.一切正常,如果我知道他们的 IP
我正在开发一个小型客户端1/客户端2、服务器(线程)TCP 游戏。在尝试处理延迟问题时,我意识到我的 transmitState() 中存在缺陷。它强制将不必要的信息传递到通讯流中,从而造成迟缓,将汽
来自文档:Configurable token lifetimes in Azure Active Directory (Public Preview) 它提到“ secret 客户端”,刷新 tok
Apollo 客户端开发工具无法连接到我的应用程序。我已在 ApolloClient 构造函数中将 connectToDevTools 传递为 true,但没有任何 react 。我也试过this p
我想在 Pod 内使用 Fabric8 kubernetes 客户端 (java)。如何获取部署集群的 kubernetes 客户端? 我可以使用该集群的 kubeconfig 文件获取任何集群的配置
我正在阅读 the security issue with Log4j我了解此产品受此漏洞影响。但是 Oracle 客户端 11.2 和 12 是否受此问题影响? 我找不到这些产品是否使用任何 Log
Eureka 服务器设置 pom.xml 1.8 Hoxton.SR1 org.springframework.cloud spring
我有一个点对点(客户端/服务器)设置(通过本地 LAN),它使用 Netty,一个 Java 网络框架。我使用原始 TCP/IP(例如,没有 HTTP)进行通信和传输。现在,根据要求,我们希望转向 T
上一篇已经实现了ModbusTcp服务器和8个主要的功能码,只是还没有实现错误处理功能。 但是在测试客户端时却发现了上一篇的一个错误,那就是写数据成功,服务器不需要响应。 接下来要做的就是实现Modb
有没有办法将二维十六进制代码数组转换为 png 图像? 数组看起来像这样(只是更大) [ [ '#FF0000', '#00FF00' ], [ '#0000FF'
我是套接字编程的新手。每次我运行客户端程序时,它都会说“无法连接到服务器”。谁能告诉我我在哪里犯了错误。任何帮助将不胜感激。 这是client.c #include #include #inclu
我们在UNIX环境下制作了简单的client.c和server.c程序。我们使用它来传输一个简单的文本文件,首先打开它,然后读取它并使用 open、read 和 send 系统调用发送;在客户端,我接
当我的程序来自 my previous question正在响应客户端,它应该发送加密消息。 当客户端连接时,它会发送一条类似“YourMessage”的消息。现在我想做的是,当客户端连接时,应该以某
我正在使用 C 和 putty 编写客户端/服务器程序。两个 c 文件位于同一系统上。 我目前在向客户端写回其正在使用的框架以及打印我的框架时遇到问题。它打印出 3 0 9 8,但随后开始打印 134
我正在使用 C 中的 select() 制作一个模拟快餐或其他任何东西的客户端服务器。 我有客户随机点 1-5 种“食物”。服务器每 30 秒决定一次。所有客户最喜欢的食物是什么?他为那些客户提供服务
对于单机游戏,基本的游戏循环是(来源:维基百科) while( user doesn't exit ) check for user input run AI move enemies
1、CentOS安装TortoiseSVN 复制代码 代码如下: yum install -y subversion 2、SVN客户端命令
我是一名优秀的程序员,十分优秀!