I've written (rather, copied from a tutorial :P) a winsock server, in c++ which waits for the client to send a message and then closes. The server works when both the client and the server are on my PC, but when i move the client to another computer, it fails.
I think it's a problem with my ip adress but 192.168.254.4 is what i get when i type ipconfig \all
in command prompt.
Server
//******************************************************************************
//
// Main.cpp
//
// Main source file of the Listener program, which employs blocking sockets and
// Winsock to listen for outside connections.
//
// If you are not using the included Dev-C++ project file, be sure to link with
// the Winsock library, usually wsock32.lib or something similarly named.
//
// Author: Johnnie Rose, Jr. (johnnie2@hal-pc.org)
// Date: 1/08/03 (version 2)
// Website: http://www.hal-pc.org/~johnnie2/winsock.html
//
//******************************************************************************
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#define NETWORK_ERROR -1
#define NETWORK_OK 0
void ReportError(int, const char *);
using namespace std;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow) {
WORD sockVersion;
WSADATA wsaData;
int nret;
sockVersion = MAKEWORD(2, 2); // We'd like Winsock version 1.1
// We begin by initializing Winsock
WSAStartup(sockVersion, &wsaData);
// Next, create the listening socket
SOCKET listeningSocket;
listeningSocket = socket(AF_INET, // Go over TCP/IP
SOCK_STREAM, // This is a stream-oriented socket
IPPROTO_TCP); // Use TCP rather than UDP
if (listeningSocket == INVALID_SOCKET) {
nret = WSAGetLastError(); // Get a more detailed error
ReportError(nret, "socket()"); // Report the error with our custom function
WSACleanup(); // Shutdown Winsock
return NETWORK_ERROR; // Return an error value
}
// Use a SOCKADDR_IN struct to fill in address information
SOCKADDR_IN serverInfo;
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr.s_addr = INADDR_ANY; // Since this socket is listening for
// connections, any local address will do
serverInfo.sin_port = htons(8888); // Convert integer 8888 to network-byte order
// and insert into the port field
// Bind the socket to our local server address
nret = bind(listeningSocket, (LPSOCKADDR)&serverInfo, sizeof(struct sockaddr));
if (nret == SOCKET_ERROR) {
nret = WSAGetLastError();
ReportError(nret, "bind()");
WSACleanup();
return NETWORK_ERROR;
}
// Make the socket listen
nret = listen(listeningSocket, 10); // Up to 10 connections may wait at any
// one time to be accept()'ed
if (nret == SOCKET_ERROR) {
nret = WSAGetLastError();
ReportError(nret, "listen()");
WSACleanup();
re开发者_StackOverflow中文版turn NETWORK_ERROR;
}
// Wait for a client
cout << "Waiting for client" << endl;
SOCKET theClient;
theClient = accept(listeningSocket,
NULL, // Address of a sockaddr structure (see explanation below)
NULL); // Address of a variable containing size of sockaddr struct
if (theClient == INVALID_SOCKET) {
nret = WSAGetLastError();
ReportError(nret, "accept()");
WSACleanup();
return NETWORK_ERROR;
}
char Buffer[256];
recv(theClient, Buffer, 256, 0);
printf(Buffer, 2);
// Send and receive from the client, and finally,
closesocket(theClient);
closesocket(listeningSocket);
// Shutdown Winsock
WSACleanup();
system("PAUSE");
return NETWORK_OK;
}
void ReportError(int errorCode, const char *whichFunc) {
char errorMsg[92]; // Declare a buffer to hold
// the generated error message
ZeroMemory(errorMsg, 92); // Automatically NULL-terminate the string
// The following line copies the phrase, whichFunc string, and integer errorCode into the buffer
sprintf(errorMsg, "Call to %s returned error %d!", (char *)whichFunc, errorCode);
MessageBox(NULL, errorMsg, "socketIndication", MB_OK);
}
Client
//******************************************************************************
//
// Main.cpp
//
// Main source file of the Connector program, which employs blocking sockets and
// Winsock to connect to an outside server.
//
// If you are not using the included Dev-C++ project file, be sure to link with
// the Winsock library, usually wsock32.lib or something similarly named.
//
// Author: Johnnie Rose, Jr. (johnnie2@hal-pc.org)
// Date: 1/08/03 (version 2)
// Website: http://www.hal-pc.org/~johnnie2/winsock.html
//
//******************************************************************************
#include <windows.h>
#include <winsock2.h>
#include <stdio.h>
#include <iostream>
#define NETWORK_ERROR -1
#define NETWORK_OK 0
void ReportError(int, const char *);
using namespace std;
int WINAPI WinMain(HINSTANCE hInst, HINSTANCE hPrevInst, LPSTR lpCmd, int nShow) {
WORD sockVersion;
WSADATA wsaData;
int nret;
cout <<"Loading WinSock" << endl;
sockVersion = MAKEWORD(2, 2);
// Initialize Winsock as before
WSAStartup(sockVersion, &wsaData);
// Store information about the server
LPHOSTENT hostEntry;
in_addr iaHost;
iaHost.s_addr = inet_addr("192.168.254.4");
hostEntry = gethostbyaddr((const char *)&iaHost, sizeof(struct in_addr), AF_INET); // Specifying the server by its name;
// another option is gethostbyaddr()
if (!hostEntry) {
nret = WSAGetLastError();
ReportError(nret, "gethostbyaddr()"); // Report the error as before
WSACleanup();
return NETWORK_ERROR;
}
// Create the socket
cout <<"Creating Socket";
SOCKET theSocket;
theSocket = socket(AF_INET, // Go over TCP/IP
SOCK_STREAM, // This is a stream-oriented socket
IPPROTO_TCP); // Use TCP rather than UDP
if (theSocket == INVALID_SOCKET) {
nret = WSAGetLastError();
ReportError(nret, "socket()");
WSACleanup();
return NETWORK_ERROR;
}
// Fill a SOCKADDR_IN struct with address information
SOCKADDR_IN serverInfo;
serverInfo.sin_family = AF_INET;
serverInfo.sin_addr = *((LPIN_ADDR)*hostEntry->h_addr_list); // See the explanation in the tutorial
serverInfo.sin_port = htons(8888); // Change to network-byte order and
// insert into port field
cout << "Connecting to server" << endl;
// Connect to the server
nret = connect(theSocket,
(LPSOCKADDR)&serverInfo,
sizeof(struct sockaddr));
if (nret == SOCKET_ERROR) {
nret = WSAGetLastError();
ReportError(nret, "connect()");
WSACleanup();
return NETWORK_ERROR;
}
// Successfully connected!
char* Buffer;
send(theSocket, "A", 1, 0);
recv(theSocket, Buffer, 256,0);
printf(Buffer,256);
// Send/receive, then cleanup:
closesocket(theSocket);
WSACleanup();
system("PAUSE");
return 0;
}
void ReportError(int errorCode, const char *whichFunc) {
char errorMsg[92]; // Declare a buffer to hold
// the generated error message
ZeroMemory(errorMsg, 92); // Automatically NULL-terminate the string
// The following line copies the phrase, whichFunc string, and integer errorCode into the buffer
sprintf(errorMsg, "Call to %s returned error %d!", (char *)whichFunc, errorCode);
MessageBox(NULL, errorMsg, "socketIndication", MB_OK);
}
If you're running the unmodified client code on a different machine, it's probably still trying to connect to a server on "localhost", which is not what you want. [Edit: OP has updated his client code and is now using an IP address.]
In a typical home/office LAN setup, you probably want to use IP addresses rather than hostnames to specify the server to use. You may also need to check that the network port you've specified is not blocked by software firewalls on the client or server machines, or by a hardware firewall or router between the server and client.
One way to debug such a problem is to use a tool like Wireshark to monitor the network traffic between the client and server. Are packets leaving the client's machine when it attempts to establish a connection? Are the requests seen by the server's machine? Is one side or the other prematurely closing the connection? Remember that firewalls can block outgoing traffic as well as incoming traffic...
精彩评论