我的问题在于:
server.sin_addr.s_addr = inet_addr("127.0.0.1");
在客户端路径中。如果我把我的地址改为127.0.0.1,那么服务器就没有响应。 我需要通过wireshark数据包嗅探器来查看此程序中的流量...
//Client
#define TIME_PORT 27015
#define NUM_OF_REQUEST 5
#define SIZE 10
int getRequestFromUser();
float calculateAverage(int* arr);
void main()
{
//allocating memory to get the needed information from user
// Initialize Winsock (Windows Sockets).
WSAData wsaData;
if (NO_ERROR != WSAStartup(MAKEWORD(2,2), &wsaData))
{
cout<<"Time Client: Error at WSAStartup()\n";
}
// Client side:
// Create a socket and connect to an internet address.
SOCKET connSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (INVALID_SOCKET == connSocket)
{
cout<<"Time Client: Error at socket(): "<<WSAGetLastError()<<endl;
WSACleanup();
return;
}
// For a client to communicate on a network, it must connect to a server.
// Need to assemble the required data for connection in sockaddr structure.
// Create a sockaddr_in object called server.
sockaddr_in server;
server.sin_family = AF_INET;
server.sin_addr.s_addr = inet_addr("127.0.0.1");
server.sin_port = htons(TIME_PORT);
// Send and receive data.
int bytesSent = 0;
int bytesRecv = 0;
char sendBuff[255];
char recvBuff[255];
int requestFromUser = -1;
while(requestFromUser != 0){
requestFromUser=getRequestFromUser();
// for mmeasure RTT/Delay
float average=0;
bool findDelay=false;
bool findRTT=false;
//matching between numbers and what they mean:
switch (requestFromUser)
{
case 1:
strcpy(sendBuff,"GetTime");
break;
case 2:
strcpy(sendBuff,"GetTimeWithoutYear");
break;
case 3:
strcpy(sendBuff,"GetTimeSinceEpoch");
break;
case 4:
{
strcpy(sendBuff,"GetClientToServerDelayEstimation");
findDelay=true;
break;
}
case 5:
{
strcpy(sendBuff,"MeasureRTT");
findRTT=true;
break;
}
case 6:
{
strcpy(sendBuff, "GetDayAndMonth");
break;
}
default:
;//don't exist
}
// Asks the server what's the currnet time.
// The send function sends data on a connected socket.
// The buffer to be sent and its size are needed.
// The fourth argument is an idicator specifying the way in which the call is made (0 for default).
// The two last arguments hold the details of the server to communicate with.
// NOTE: the last argument should always be the actual size of the client's data-structure (i.e. sizeof(sockaddr)).
if (findDelay)
{
int i;
long int arrTimeR[SIZE];
int arrTime[SIZE];
time_t arrTimeSend[SIZE];
//Start sending the request
strcpy(sendBuff,"GetTimeSinceEpoch");
for (i=0; i<SIZE; i++)
{
//sending request
bytesSent = sendto(connSocket, sendBuff, (int)strlen(sendBuff), 0, (const sockaddr *)&server, sizeof(server));
arrTimeSend[i]= time (NULL);
if (SOCKET_ERROR == bytesSent)
{
cout<<"Time Client: Error at sendto(): "<<WSAGetLastError()<<endl;
closesocket(connSocket);
WSACleanup();
return;
}
//recieving data
bytesRecv = recv(connSocket, recvBuff, 255, 0);
if (SOCKET_ERROR == bytesRecv)
{
cout<<"Time Client: Error at recv(): "<<WSAGetLastError()<<endl;
closesocket(connSocket);
WSACleanup();
return;
}
recvBuff[bytesRecv]='\0';
arrTime[i]=atoi(recvBuff)-(arrTimeSend[i]);
}//for
average=calculateAverage(arrTime);
cout<< "The average Delay between Client to Server is "<<average<<" in seconds\n";
}//findDelay
if (findRTT)
{
int i;
time_t timerD;
time_t arrTimeSend[SIZE];
int arrTime[SIZE];
strcpy(sendBuff,"GetTime");
for (i=0; i<SIZE; i++)
{
//getting time of sending I'm including all operations for sending the request to the server
arrTimeSend[i]=time (NULL);
//sending request
bytesSent = sendto(connSocket, sendBuff, (int)strlen(sendBuff), 0, (const sockaddr *)&server, sizeof(server));
if (SOCKET_ERROR == bytesSent)
{
cout<<"Time Client: Error at sendto(): "<<WSAGetLastError()<<endl;
closesocket(connSocket);
WSACleanup();
return;
}
}//for sending
for (i=0; i<SIZE; i++)
{
//recieving data
bytesRecv = recv(connSocket, recvBuff, 255, 0);
//getting time of recieving
timerD = time (NULL);
if (SOCKET_ERROR == bytesRecv)
{
cout<<"Time Client: Error at recv(): "<<WSAGetLastError()<<endl;
closesocket(connSocket);
WSACleanup();
return;
}
recvBuff[bytesRecv]='\0';//not needed for calculation , but for future use
arrTime[i]=difftime(timerD,arrTimeSend[i]);
}//for receving
average=calculateAverage(arrTime);
cout<< "The average RTT time is "<<average<<" in seconds\n";
}//findRTT
if (!findRTT && !findDelay)
{
bytesSent = sendto(connSocket, sendBuff, (int)strlen(sendBuff), 0, (const sockaddr *)&server, sizeof(server));
if (SOCKET_ERROR == bytesSent)
{
cout<<"Time Client: Error at sendto(): "<<WSAGetLastError()<<endl;
closesocket(connSocket);
WSACleanup();
return;
}
cout<<"Time Client: Sent: "<<bytesSent<<"/"<<strlen(sendBuff)<<" bytes of \""<<sendBuff<<"\" message.\n";
// Gets the server's answer using simple recieve (no need to hold the server's address).
bytesRecv = recv(connSocket, recvBuff, 255, 0);
if (SOCKET_ERROR == bytesRecv)
{
cout<<"Time Client: Error at recv(): "<<WSAGetLastError()<<endl;
closesocket(connSocket);
WSACleanup();
return;
}
recvBuff[bytesRecv]='\0'; //add the null-terminating to make it a string
cout<<"Time Client: Recieved: "<<bytesRecv<<" bytes of \""<<recvBuff<<"\" message.\n";
}//(!findRTT && !findDelay)
}//End of while
// Closing connections and Winsock.
cout<<"Time Client: Closing Connection.\n";
closesocket(connSocket);
//free the allocating memory
}//main
//==================
int getRequestFromUser()
{
int num=0;
//int index=0;
//char c;
cout<<"Choose the information that you intrested in:"<<endl;
cout<<"(1) - Get time"<<endl;
cout<<"(2) - Get time without Year"<<endl;
cout<<"(3) - Get time since epoch - meanning since 1.1.1970"<<endl;
cout<<"(4) - Get dilay time "<<endl;
cout<<"(5) - measuring RTT - round trip time"<<endl;
cout<<"(6) - Get day and month"<<endl;
cout<<"(0) - Exit"<<endl;
cin>>num;
return num;
}
float calculateAverage(int* arr)
{
int sum=0,i;
for (i=0; i<SIZE; i++)
sum+=arr[i];
return sum/SIZE;
}
//Server
#include <iostream>
using namespace std;
#include <winsock2.h>
#include <string.h>
#include <time.h>
#include <iomanip>
#define TIME_PORT 27015
void main()
{
// Initialize Winsock (Windows Sockets).
// Create a WSADATA object called wsaData.
// The WSADATA structure contains information about the Windows
// Sockets implementation.
WSAData wsaData;
// Call WSAStartup and return its value as an integer and check for errors.
// The WSAStartup function initiates the use of WS2_32.DLL by a process.
// First parameter is the version number 2.2.
// The WSACleanup function destructs the use of WS2_32.DLL by a process.
if (NO_ERROR != WSAStartup(MAKEWORD(2,2), &wsaData))
{
cout<<"Time Server: Error at WSAStartup()\n";
}
// Server side:
// Create and bind a socket to an internet address.
// After initialization, a SOCKET object is ready to be instantiated.
// Create a SOCKET object called m_socket.
// For this application: use the Internet address family (AF_INET),
// datagram sockets (SOCK_DGRAM),
// and the UDP/IP protocol (IPPROTO_UDP).
SOCKET m_socket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
// Check for errors to ensure that the socket is a valid socket.
// Error detection is a key part of successful networking code.
// If the socket call fails, it returns INVALID_SOCKET.
// The "if" statement is used to catch any errors that
// may have occurred while creating the socket. WSAGetLastError returns an
// error number associated with the last error that occurred.
if (INVALID_SOCKET == m_socket)
{
cout<<"Time Server: Error at socket(): "<<WSAGetLastError()<<endl;
WSACleanup();
return;
}
// For a server to communicate on a network, it must first bind the socket to
// a network address.
// Need to assemble the required data for connection in sockaddr structure.
// Create a sockaddr_in object called serverService.
sockaddr_in serverService;
// Address family (must be AF_INET - Internet address family).
serverService.sin_family = AF_INET;
// IP address. The sin_addr is a union (s_addr is a unsigdned long (4 bytes) data type).
// INADDR_ANY means to listen on all interfaces.
// inet_addr (Internet address) is used to convert a string (char *) into unsigned int.
// inet_ntoa (Internet address) is the reverse function (converts unsigned int to char *)
// The IP address 127.0.0.1 is the host itself, it's actually a loop-back.
serverService.sin_addr.s_addr = INADDR_ANY; //inet_addr("127.0.0.1");
// IP Port. The htons (host to network - short) function converts an
// unsigned short from host to TCP/IP network byte order (which is big-endian).
serverService.sin_port = htons(TIME_PORT);
// Bind the socket for client's requests.
// The bind function establishes a connection to a specified socket.
// The function uses the socket handler, the sockaddr structure (which
// defines properties of the desired connection) and the length of the
// sockaddr structure (in bytes).
if (SOCKET_ERROR == bind(m_socket, (SOCKADDR *) &serverService, sizeof(serverService)))
{
cout<<"Time Server: Error at bind(): "<<WSAGetLastError()<<endl;
closesocket(m_socket);
WSACleanup();
return;
}
// Waits for incoming requests from clients.
// Send and receive data.
sockaddr client_addr;
int client_addr_len = sizeof(client_addr);
int bytesSent = 0;
int bytesRecv = 0;
char sendBuff[255];
char recvBuff[255];
// Get client's requests and answer them.
// The recvfrom function receives a datagram and stores the source address.
// The buffer for data to be received and its available size are
// returned by recvfrom. The fourth argument is an idicator
// specifying the way in which the call is made (0 for default).
// The two last arguments are optional and will hold the details of the client for further communication.
// NOTE: the last argument should always be the actual size of the client's data-structure (i.e. sizeof(sockaddr)).
cout<<"Time Server: Wait for clients' requests.\n";
while(true)
{
bytesRecv = recvfrom(m_socket, recvBuff, 255, 0, &client_addr, &client_addr_len);
if (SOCKET_ERROR == bytesRecv)
{
cout<<"Time Server: Error at recvfrom(): "<<WSAGetLastError()<<endl;
closesocket(m_socket);
WSACleanup();
return;
}
recvBuff[bytesRecv]='\0'; //add the null-terminating to make it a string
cout<<"Time Server: Recieved: "<<bytesRecv<<" bytes of \""<<recvBuff<<"\" message.\n";
time_t timer;
time(&timer);
char date [10];
char dayAndMonth [6];
//1-GetTime
if (strcmp(recvBuff,"GetTime")==0){
strcpy(sendBuff, ctime(&timer));
sendBuff[strlen(sendBuff)-1] = 0;
}
//2-GetTimeWithoutYear
else if (strcmp(recvBuff,"GetTimeWithoutYear")==0){
struct tm * timeinfo = localtime(&timer);
strftime (sendBuff,255,"%X",timeinfo);
sendBuff[strlen(sendBuff)] = 0;
}
//3-GetTimeSinceEpoch
else if (strcmp(recvBuff,"GetTimeSinceEpoch")==0){
timer = time (NULL);
itoa(timer,sendBuff,10);//converting from int to srting
strcat (sendBuff," seconds.");
sendBuff[strlen(sendBuff)] = 0;
}
//6 - GetDayAndMonth
else if(strcmp(recvBuff, "GetDayAndMonth")==0)
{
_tzset;
_strdate(date);
strncpy(dayAndMonth, date, 5);
dayAndMonth[5] = '\0';
strcpy(sendBuff, dayAndMonth);
sendBuff[strlen(sendBuff)] = 0;
}
// Sends the answer to the client, using the client address gathered
// by recvfrom.
bytesSent = sendto(m_socket, sendBuff, (int)strlen(sendBuff), 0, (const sockaddr *)&client_addr, client_addr_len);
if (SOCKET_ERROR == bytesSent)
{
cout<<"Time Server: Error at sendto(): "<<WSAGetLastError()<<endl;
closesocket(m_socket);
WSACleanup();
return;
}
cout<<"Time Server: Sent: "<<bytesSent<<"\\"<<strlen(sendBuff)<<" bytes of \""<<sendBuff<<"\" message.\n";
}
// Closing connections and Winsock.
cout<<"Time Server: Closing Connection.\n";
closesocket(m_socket);
WSACleanup();
}
答案 0 :(得分:1)
我的问题在于: server.sin_addr.s_addr = inet_addr(“127.0.0.1”); 在客户路径中。如果我把我的地址改为127.0.0.1,那么服务器就没有响应。 我需要通过wireshark数据包嗅探器来查看此程序中的流量...
答案 1 :(得分:0)
您可能需要先执行一些 ping YOUR_SERVER 命令,或者通过异常处理找出,可能是您的服务器不可用。
答案 2 :(得分:0)
如果我理解正确,你必须使用环回地址(127.0.0.1)与你的服务器通信,问题是,如果这样做,你无法在Wireshark中看到流量。
这是正确的,并假设(如您的代码所示)您在Windows上,我担心您运气不好。请参阅:http://wiki.wireshark.org/CaptureSetup/Loopback
您是否可以更改服务器以使其在另一个地址上进行侦听?