Categories: MSDN / DotNet / Java / Scripts / Linux / PHP Ask - La ask - La Answer

[WINSOCK]- Basic Client/Server Help

I am starting to learn more within winsock, so I decided to try to make a verrrry simple client + server. The server listens on port 6112, and waits for a client to connect and send the string "test", once it has recived "test" from a client, it replies back with "Back Test". The client just connects to my local IP(192.168.0.4), and sends the string, "test" and waits for the server to send data. However, when I try starting the server, and then running the client, I get nothing. I believe they connect, because the CMD prompt remains open, and I get none of the error's. I also tried attaching WPE to the server and client, and no packet's are being sent. Here is the code:

*Server*

//Server.cpp
#include <winsock.h>
#include <iostream>
#pragma comment(lib, "ws2_32")

using namespace std;

SOCKET s;
WSADATA w;
SOCKADDR_IN t;

bool StartandListen() {
int error = WSAStartup(MAKEWORD(2, 2), &w);

if (error) {
cout << "Error at WSAStartup()\n";
return false;
}

s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (s == INVALID_SOCKET) {
cout << "Error at socket().\n";
WSACleanup();
return false;
}

t.sin_family = AF_INET;
t.sin_port = htons(6112);
t.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(s, (SOCKADDR *)&t, sizeof(t)) == SOCKET_ERROR) {
cout << "Failed to bind on port 6112.\n";
WSACleanup();
return false;
}

if (listen(s, 1) == SOCKET_ERROR) {
cout << "Error listening.\n";
return false;
}

cout << "Server started and listening.\n";

return true;
}

int main() {
StartandListen();

char recvd[50];
char sendBuff[50];

do {
recv(s, recvd, strlen(recvd), 0);

if (!strcmp(recvd, "test")) {
strcpy(sendBuff, "Back Test");
send(s, sendBuff, strlen(sendBuff), 0);
cout << "Recieved message test.\n";
}
}while(1);

return 0;
}

*Client*

//client.cpp
#include <winsock.h>
#include <iostream>
#pragma comment(lib, "ws2_32")

using namespace std;

int main() {
SOCKADDR_IN target;
SOCKET sock;
WSADATA wsadata;
char sendBuff[32];
char recvBuff[32];

int error = WSAStartup(MAKEWORD(2, 2), &wsadata);

if (error) {
cout << "Error.\n";
return 0;
}

target.sin_family = AF_INET;
target.sin_port = htons(6112);
target.sin_addr.s_addr = inet_addr("192.168.0.4"); //my local IP

sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (connect(sock, (SOCKADDR *)&target, sizeof(target)) == SOCKET_ERROR) {
cout << "connect() error.\n";
return 0;
}

if (sock == SOCKET_ERROR) {
cout << "Socket error.\n";
return 0;
}

strcpy(sendBuff, "test");
send(sock, sendBuff, strlen(sendBuff), 0);

do {
if (recv(sock, recvBuff, strlen(recvBuff), 0) == SOCKET_ERROR) {
cout << "recv() error.\n";
return 0;
}

cout << recvBuff;

}while(1);

return 0;
}

Any help would be appreciated, Thanks.
[3388 byte] By [JiK] at [2007-11-11 10:17:28]
# 1 Re: [WINSOCK]- Basic Client/Server Help
I think you need to execute accept after listen:
bool StartandListen()
{
. . .
cout << "Server started and listening.\n";
SOCKET accepted_socket;
accepted_socket = accept(s, NULL, NULL);
}
Note that the server must use this accepted_socket instead of s in subsequent recv and send calls.

I hope this helps.
Viorel at 2007-11-11 20:59:03 >
# 2 Re: [WINSOCK]- Basic Client/Server Help
Thanks for helping, it is still not working properly, I updated the server.cpp to this:

//Server.cpp
#include <winsock.h>
#include <iostream>
#pragma comment(lib, "ws2_32")

using namespace std;

SOCKET s;
WSADATA w;
SOCKADDR_IN t;
SOCKET accepted_socket;

bool StartandListen() {
int error = WSAStartup(MAKEWORD(2, 2), &w);

if (error) {
cout << "Error at WSAStartup()\n";
return false;
}

s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if (s == INVALID_SOCKET) {
cout << "Error at socket().\n";
WSACleanup();
return false;
}

t.sin_family = AF_INET;
t.sin_port = htons(6112);
t.sin_addr.s_addr = htonl(INADDR_ANY);

if (bind(s, (SOCKADDR *)&t, sizeof(t)) == SOCKET_ERROR) {
cout << "Failed to bind on port 6112.\n";
WSACleanup();
return false;
}

if (listen(s, 1) == SOCKET_ERROR) {
cout << "Error listening.\n";
return false;
}

cout << "Server started and listening.\n";

accepted_socket = accept(s, NULL, NULL);

return true;
}

int main() {
StartandListen();

char recvd[50];
char sendBuff[50];

do {
recv(accepted_socket, recvd, strlen(recvd), 0);

if (!strcmp(recvd, "test")) {
strcpy(sendBuff, "Back Test");
send(accepted_socket, sendBuff, strlen(sendBuff), 0);
cout << "Recieved message test.\n";
}
}while(1);

return 0;
}

And I left the client untouched, any idea why it is still not working?
JiK at 2007-11-11 21:00:08 >
# 3 Re: [WINSOCK]- Basic Client/Server Help
When you specify the buffer size in recv operation using expressions like strlen(recvd), the value is unpredictable, since recvd does not contain a valid string. I think you should try sizeof(recvd) instead, in all of your recv calls.

Additionally, when you send a string, you probably must send the terminator too. Therefore I think you have to use expressions like strlen(sendBuff) + 1. Or may be better is to send the length first, and then the characters. Receivers have to be adjusted too.
Viorel at 2007-11-11 21:01:14 >
# 4 Re: [WINSOCK]- Basic Client/Server Help
I tried what you have just suggested, and I am still getting nothing. Also, when using WPE(Winsock Packet Editor), both the Client and Server are not sending or receiving anything.
JiK at 2007-11-11 21:02:08 >
# 5 Re: [WINSOCK]- Basic Client/Server Help
First of all, always initialize yoru buffers before using them:

char recvd[50] = {0};
char sendBuff[50]= {0};

Secondly, don't use strlen for non-string data. Instead, use sizeof(recd) or a constant:

char recvd[MAX] = {0};
recv(accepted_socket, recvd, MAX, 0);
Danny at 2007-11-11 21:03:12 >
# 6 Re: [WINSOCK]- Basic Client/Server Help
Alright, thanks it is starting to work. Have a few bug's to work out, but its working, Thanks Viorel and Danny
JiK at 2007-11-11 21:04:11 >