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;
}