Skip to main content
gamedev.net
🔒 Locked

Need help on basic telnet program

Started by MrSnausage 3 replies 600+ views
Original Post
MrSnausage
MrSnausage
In the process of learning winsock, I am trying to create a very basic winsock program that will allow me to connect to an ip address and a port and receive data and issue commands. My program connects to the server, it starts a loop that retrieves the information first in case the server sends something immediately like an smtp server, and then allows me to send a command. My problem is that after I send a command it locks up. When I did the debugging with dev-cpp it shows that its locking up when the loop begins again and i issue the recv function again. Enclosed is the code. Can anyone please give me an idea of what I am doing wrong. Thanks in advance and code below. Code: #include <stdio.h> #include <winsock2.h> #include <string.h> void printerror(char *); int main(int argc, char *argv[]) { WSADATA wsa; SOCKET s; struct sockaddr_in target; struct hostent *rhost; char sbuffer[500]; char rbuffer[500]; int rbytesReceived,sbytesSent; int iostate = 1; rbytesReceived = sbytesSent = 0; if(argc != 3) { printf("Syntax: telnet ipaddress port\n"); return 1; } if((atoi(argv[2])) > 65536) { printf("Port must be between 1 and 65536"); return 1; } if(WSAStartup(MAKEWORD(2,2),&wsa)) { printerror("WSAStartup()"); return 1; } rhost = gethostbyname(argv[1]); if(rhost == NULL) { printerror("gethostbyname()"); return 1; } s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if(s == INVALID_SOCKET) { printerror("socket()"); WSACleanup(); return 1; } target.sin_family = AF_INET; target.sin_port = htons(atoi(argv[2])); target.sin_addr.s_addr = inet_addr(inet_ntoa(*(LPIN_ADDR) *(rhost->h_addr_list))); memset(&(target.sin_zero),''\0'',8); if(connect(s,(struct sockaddr*) ⌖,sizeof(struct sockaddr)) == -1) { printerror("connect()"); closesocket(s); WSACleanup(); return 1; } do { memset(sbuffer,''\0'',500); // To null out the buffer. Not sure if its needed. memset(rbuffer,''\0'',500); rbytesReceived = recv(s,rbuffer,sizeof(rbuffer),0); if(rbytesReceived == SOCKET_ERROR) { printerror("recv()"); closesocket(s); WSACleanup(); return 1; } rbuffer[rbytesReceived]=''\0''; puts(rbuffer); gets(sbuffer); // Ask for input. sbytesSent = send(s,sbuffer,sizeof(strlen(sbuffer)),0); if(sbytesSent == SOCKET_ERROR) { printerror("send()"); closesocket(s); WSACleanup(); return 1; } } while(strcmp(sbuffer,"quit")); // If input is quit, exit program. closesocket(s); WSACleanup(); return 0; } void printerror(char *function) { LPVOID lpMsgBuf; FormatMessage( FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS, NULL, WSAGetLastError(), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language (LPTSTR) &lpMsgBuf, 0, NULL) ; printf("Error in %s:\n%s\n",function,(LPCTSTR)lpMsgBuf); LocalFree( lpMsgBuf ); }
krez
krez
the recv() function blocks until data arrives, unless you set the socket to non-blocking. so, if the server you connect to doesn''t send anything, recv() will lock up your app.

you must either make the socket non-blocking, or only read from it when data is available.
--- krez ([email="krez_AT_optonline_DOT_net"]krez_AT_optonline_DOT_net[/email])
MrSnausage
MrSnausage
What functions would i use to accept data when its available?

Also when i set the socket to non-blocking, i get the following error when trying to run the program:

Error in connect():
A non-blocking socket operation could not be completed immediately.

MrSnausage
MrSnausage
On a side not, when I use this program against an smtp server for example. It properly prints the smtp banner and then waits for input. It is only after i give input that it locks up.

Since i entered input, the mail server should send data back immediately, which I would think would be picked up by the recv in the next iteration of the loop which is where it is freezing.

Thats why im confused as to why this would be a blocking issue.
wrathgame
wrathgame
Hi, I looked at your code and what was happening was:
1) u connect
2) u recieved the welcome message
3) u sent some message.. which the smtp server didnt think was a full message and so is still waiting for more info
4) u do a blocking recieve on the connection at which point it hands because the smtp is not sending cuz its waiting on you

I have changed your code to make it nonblocking but please not that this is still a bad system because it doesnt recieve any data while its waiting for your input

good luck


#include <stdio.h>
#include <winsock2.h>
#include <string.h>

void printerror(char *);

int main(int argc, char *argv[]) {
WSADATA wsa;
SOCKET s;
struct sockaddr_in target;
struct hostent *rhost;
char sbuffer[500];
char rbuffer[500];
int rbytesReceived,sbytesSent;
int iostate = 1;
int err;

rbytesReceived = sbytesSent = 0;

if(argc != 3) {
printf("Syntax: telnet ipaddress port\n");
return 1;
}

if((atoi(argv[2])) > 65536) {
printf("Port must be between 1 and 65536");
return 1;
}

if(WSAStartup(MAKEWORD(2,2),&wsa)) {
printerror("WSAStartup()");
return 1;
}

rhost = gethostbyname(argv[1]);

if(rhost == NULL) {
printerror("gethostbyname()");
return 1;
}

s = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);

if(s == INVALID_SOCKET) {
printerror("socket()");
WSACleanup();
return 1;
}

unsigned long ul = 1;
int nRet = ioctlsocket( s, FIONBIO, (unsigned long *)&ul );
if(nRet == SOCKET_ERROR) {
printerror("ioctlsocket()");
closesocket(s);
WSACleanup();
return 1;
}

target.sin_family = AF_INET;
target.sin_port = htons(atoi(argv[2]));
target.sin_addr.s_addr = inet_addr(inet_ntoa(*(LPIN_ADDR) *(rhost->h_addr_list)));
memset(&(target.sin_zero),'\0',8);

if(connect(s,(struct sockaddr*) ⌖,sizeof(struct sockaddr)) == -1) {
err=WSAGetLastError();
if(err!=WSAEWOULDBLOCK)
{
printerror("connect()");
closesocket(s);
WSACleanup();
return 1;
}
}

do {
memset(sbuffer,'\0',500); // To null out the buffer. Not sure if its needed.
memset(rbuffer,'\0',500);

rbytesReceived = recv(s,rbuffer,sizeof(rbuffer),0);

if(rbytesReceived == SOCKET_ERROR) {
err=WSAGetLastError();
if(err!=WSAEWOULDBLOCK)
{
printerror("recv()");
closesocket(s);
WSACleanup();
return 1;
}
}
rbuffer[rbytesReceived]='\0';
puts(rbuffer);

gets(sbuffer); // Ask for input.

sbytesSent = send(s,sbuffer,sizeof(strlen(sbuffer)),0);

if(sbytesSent == SOCKET_ERROR) {
err=WSAGetLastError();
if(err!=WSAEWOULDBLOCK)
{
printerror("send()");
closesocket(s);
WSACleanup();
return 1;
}
}

} while(strcmp(sbuffer,"quit")); // If input is quit, exit program.

closesocket(s);

WSACleanup();
return 0;
}



void printerror(char *function) {
LPVOID lpMsgBuf;

FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER |
FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_IGNORE_INSERTS,
NULL,
WSAGetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0,
NULL) ;
printf("Error in %s:\n%s\n",function,(LPCTSTR)lpMsgBuf);
LocalFree( lpMsgBuf );
}


~ Tim

[edited by - wrathgame on May 16, 2003 9:35:17 AM]
~ Tim

Topic Locked

This topic has been locked by a moderator. New replies are not allowed.

Sign in to reply to this topic.