I've spent at least 2 last hours searching for a way to make a simple connection to a POP3 server and get the number of messages waiting on it. As it's childlish-easy in C# and seems pretty basic in C++ on linux, I just can't find even the slightest tutorial on how to make it work on Windows.
I don't want to use any third-party libraries - i just want to code a simple console program, using raw C++ only, just to do some basic stuff as described above. All the sources I've tried to study are like:
POP3 is a protocol that has somethng to do with emails and it's very simple. Now let's proceed to writing a multi-platform POP3 server-client application, using a F16 fighter jet and inventing a time machine in progress.
I just can't seem to find any SIMPLE solutions...
I've written (with some help) a simple snippet that SHOULD work on linux - at least according to the tutorials; I have no means to check it right now.
Hovewer, the C++ is not my "native language" and when I try to transfer it into Windows, I just fall from one hole into the other and have to spend yet another quarter of an hour GGoogle'ing the solution.
At this point, the code is compiling, but the linker fails. It's strange, because I've added the ws2_32.lib to the linker, so it SHOULD work just fine. In return, I only get loads of LNK2019.
Can you please help me with the code or provide any link to a SIMPLE solution that works on Windows?
The code:
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN 1
#include <winsock2.h>
#include <windows.h>
#else
#endif
#ifndef in_addr_t
#define in_addr_t long
#endif
#include <string.h>
void err(char *where) {
fprintf(stderr, "error in %s: %d\n", where, errno);
exit(1);
}
int main(int argc, char *argv[]) {
char *remote = "some_address";
struct servent *sent;
struct protoent *pent;
int port;
int sock;
int result;
in_addr_t ipadr;
struct sockaddr_in addr;
struct hostent *hent;
char buf[2048];
sent = getservbyname("http", "pop3");
if(sent == NULL)
err("getservbyname");
port = sent->s_port;
pent = getprotobyname("pop3");
if(pent == NULL)
err("getprotobyname");
hent = gethostbyname(remote);
printf("Host: %s\n", hent->h_name);
printf("IP: %s\n", inet_ntoa(*((struct in_addr *)hent->h_addr)));
addr.sin_family = AF_INET;
addr.sin_port = port;
addr.sin_addr = *((struct in_addr *)hent->h_addr);
memset(addr.sin_zero, '\0', 8);
sock = socket(AF_INET, SOCK_STREAM, pent->p_proto);
if(sock < 0)
err("socket");
result = connect(sock, (struct sockaddr *)&addr, sizeof(struct sockaddr));
if(result < 0)
err("connect");
}
You have to add WSAStartup before you use any Winsock function. When you are done, you have to call WSACleanup.
Example(from msdn):
WORD wVersionRequested;
WSADATA wsaData;
int err;
wVersionRequested = MAKEWORD(2, 2);
err = WSAStartup(wVersionRequested, &wsaData);
if (err != 0)
{
return 1;
}
//Do stuf here
WSACleanup();
Related
I have a server and when a client connects to the server, I want to take all the information from the client and make a struct with it.
What information can I get?
I know that I can get the ipv4 and port from the client, there is anything left that I can get?
This is a short way of doing it:
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include <windows.h>
#include <winsock2.h>
#include <ws2tcpip.h>
#include <iostream>
#pragma comment (lib, "Ws2_32.lib")
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT 32406
int main()
{
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 2), &wsaData);
sockaddr_in hint;
hint.sin_addr.S_un.S_addr = INADDR_ANY;
hint.sin_port = htons(DEFAULT_PORT);
hint.sin_family = AF_INET;
SOCKET listeningSocket = socket(AF_INET, SOCK_STREAM, 0);
bind(listeningSocket, (sockaddr*)&hint, sizeof(sockaddr_in));
listen(listeningSocket, SOMAXCONN);
sockaddr_in socketInfo;
int socketInfoLen = sizeof(socketInfo);
SOCKET clientSocket = accept(listeningSocket, (sockaddr*)&socketInfo, &socketInfoLen);
std::cout << inet_ntoa(socketInfo.sin_addr) << std::endl;
std::cout << socketInfo.sin_port << std::endl;
shutdown(clientSocket, SD_BOTH);
closesocket(clientSocket);
closesocket(listeningSocket);
WSACleanup();
return 0;
}
There is a whole lot of information available from getsockopt. It is a superset of what the other answer claims, for example
SO_BSP_STATE Returns the local address, local port, remote address, remote port, socket type, and protocol used by a socket.
Since you have a TCP socket you will be particularly interested in
IPPROTO_TCP socket options
There is different information available through WSAIoctl, for example
TCP_INFO_v1 structure
Some of these details will be local socket options (such as blocking or non-blocking), others will relate to the connection itself (e.g. negotiated window size). Some information about the remote client will be revealed, although not as much as if you used a bespoke fingerprinting tool.
Here is the implementation of #Ben Voigt's answer, if someone needs it:
#include <WinSock2.h>
#pragma comment (lib, "Ws2_32.lib")
bool GetSocketState(SOCKET sock, CSADDR_INFO& state) {
union CSADDR_INFO_PADDED {
CSADDR_INFO csaddr;
TCHAR padding[128];
} csaddrPadded {};
int infoLen = sizeof(csaddrPadded);
if (getsockopt(sock, SOL_SOCKET, SO_BSP_STATE, (TCHAR*)&csaddrPadded, &infoLen)) {
return false;
}
state = csaddrPadded.csaddr;
return true;
}
The only information you get that the client doesn't explicitly send is the sockaddr_in structure, ie the port and source IP address. Though of course you only get this when the client initiates a transfer (sends a packet with UDP or connects with TCP).
To get anything else, the client needs to send it as part of regular communication.
I have made a pretty simple http client which would retrieve html from http website and print it. But there seems to be some problem while using connect() function.Using perror() I found that it is giving connection refused error.
This is my code
#include <string.h>
#include <stdio.h>
#include <iostream>
#include <sys/socket.h>
#include <unistd.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main(int argc, char *argv[])
{
char *address;
address = argv[1];
int c_socket = socket(AF_INET, SOCK_STREAM, 0);
struct sockaddr_in URLaddress;
URLaddress.sin_family = AF_INET;
URLaddress.sin_port = htons(80);
inet_pton(0,address,&URLaddress.sin_addr.s_addr);
int con = connect(c_socket, (struct sockaddr*) &URLaddress,
sizeof(URLaddress));
perror("error");
return 0;
}
This is the input
151.101.13.5
This is the output
error: Connection refused
I am passing IP of website as input.
I have seen all other similar questions but didn't get any answer as how to fix this because this keeps happening with every website I try my program with.
Please tell how to resolve this.
The following version of the code works on Windows/MSC:
int test(void)
{
char *address;
int c_socket, con;
struct sockaddr_in URLaddress;
char request[] = "GET / HTTP/1.1\r\n\r\n";
char response[4096];
WORD wVersionRequested;
WSADATA wsaData;
wVersionRequested = MAKEWORD( 2, 2 );
address = "151.101.13.5";
if (WSAStartup (wVersionRequested, &wsaData)!= 0) {
printf("DLL not found\n");
return -1;
}
if ((c_socket = socket(AF_INET, SOCK_STREAM, 0)) == INVALID_SOCKET ) {
printf("socket error: %d\n", WSAGetLastError());
return -1;
}
URLaddress.sin_family = AF_INET;
URLaddress.sin_port = htons(80);
URLaddress.sin_addr.s_addr= inet_addr(address);
con = connect(c_socket, (struct sockaddr*) &URLaddress, sizeof(URLaddress));
send(c_socket, request, strlen(request), 0);
recv(c_socket, response, sizeof(response), 0);
WSACleanup();
printf ("%s\n",response);
return 0;
}
The repsonse is:
<title>Fastly error: unknown domain </title>
</head>
<body>
<p>Fastly error: unknown domain: . Please check that this domain has been added to a service.</p>
<p>Details: cache-fra19128-FRA</p></body></html>5¸`¡qu
inet_pton(3) requires a first parameter to specify the address family and you have passed 0 for it (which is not the same as AF_INET), and you had to pass AF_INET, in accordance of the protocol family you are using.
inet_pton(3) is a protocol family independent conversion routine, but it needs to know what is the actual used to be able to convert addresses properly.
By the way, is a server listening on the requested address and port? have you tested that a browser is capable of getting something from that address before running your program?
I am trying to write a program for my raspberry pi that changes its system time to the time from a GPS unit on the same network. The GPS sends out a 72 byte UDP packet across port 3000. I am new to socket programming so I am unsure where I am going wrong.
The trouble that I am having is that I can't seem to get it to build with g++. I am getting the following error:
So the main error seems to be in the line
char A = struct sockaddr_in address;
Here is the start of my program and the method where I create the socket and where the error is located, if you would like the main method of my program then I will add it too.
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <time.h>
#include <sys/time.h>
#include <errno.h>
#include <math.h>
// defines the socket used by the GPS
#define PORT 3000
/****************************/
int CreateSocket(int port)
/****************************/
{
// Create an UDP-socket
int sock = socket(AF_INET, SOCK_DGRAM, 0);
// Check if UDP-socket was created
if(sock==-1)
{
fprintf(stderr, "1CreateSocket: socket failed\n");
return -1;
}
// Bind it to the local IP-address
struct sockaddr_in address;
char A = struct sockaddr_in address;
fprintf(stderr, A);
// Pointer to the block of memory to fill with address data
memset(&address, 0, sizeof(address));
address.sin_family = AF_INET; // Address family for IP-address
address.sin_addr.s_addr = htonl(INADDR_ANY); // converts the unsigned integer hostlong from host byte order to network byte order
address.sin_port = htons(port); // converts the unsigned short integer hostshort from host byte order to network byte order
// Check if IP-address is correct, if not Socket failed. Otherwise it returns the socket
if(bind(sock, (struct sockaddr *) &address, sizeof(address))==-1)
{
fprintf(stderr, "2CreateSocket: bind failed\n");
close(sock);
return -1;
}
return sock;
}
Can anyone see any obvious errors here? Thanks
You don't really need these two lines:
char A = struct sockaddr_in address;
fprintf(stderr, A);
You can delete them, since they don't do anything useful, and they have a syntax error.
And to do some extra cleanup, the comment of the binding above those lines that can be deleted should actually go above the call to bind().
In all the example including Beej's Guide, the IP address is provided in dot notation and then it's fed to ::getaddrinfo(). This post doesn't answer my question.
After which the addrinfo struct is used for socket related functions (e.g. connect(), bind(), listen()). For example:
struct addrinfo hints, *res;
// ... create socket etc.
connect(sockfd, res->ai_addr, res->ai_addrlen);
Example
The variable ai_addr is of type sockaddr which can be safely typecasted to sockaddr_storage, sockaddr_in and sockaddr_in6.
Question:
If I typecast sockaddr to sockaddr_in (or sockaddr_in6)
sockaddr_in& ipv4 = (sockaddr_in&)(sockaddr_variable);
and feed below info:
ipv4.sin_family = AF_INET
ipv4.sin_addr = [IP Address in net byte order]
ipv4.sin_port = [Port number in net byte order]
Can I call the connect() method directly using above info?
connect(sockfd, &ipv4, sizeof(ipv4));
With my program it doesn't appear to work. Am I missing something, or is there a better way?
The motivation behind is that, if we have the information of IPAddress, Port etc. in socket readable format then why to go through the cycle of getaddrinfo()
Be sure you're placing your values in network order, here's a small example:
#include<stdio.h>
#include<sys/socket.h>
#include<arpa/inet.h>
int main(int argc, char *argv[])
{
int sock;
struct sockaddr_in server;
sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1)
{
printf("Could not create socket\n");
}
printf("Socket created\n");
server.sin_family = AF_INET;
// 173.194.32.207 is a google address
server.sin_addr.s_addr = 173 | 194 << 8 | 32 << 16 | 207 << 24;
server.sin_port = 0x5000; // port 80
if (connect(sock, (struct sockaddr *)&server, sizeof(server)) < 0)
{
perror("connect failed. Error");
return 1;
}
printf("Connected\n");
close(sock);
return 0;
}
First check whether the machine is reachable & the server application is running on the machine using "netstat" utility. Use inet_aton method to convert dotted address to network byte order. Finally, log the error value returned by the connect to get the exact reason of failure.
It's worth noting that calling socket::{connect, bind, ...} is wrong: these are C APIs and C doesn't have namespaces, classes and so on.
You should use getaddrinfo as it's much easier and safer to use. But nothing prevents you from using struct sockaddr and all its variants. Indeed, getaddrinfo is a sort of wrapper as stated in man(3) getaddrinfo:
The getaddrinfo() function combines the functionality
provided by the gethostbyname(3) and getservbyname(3) functions into a
single interface, but unlike the latter functions, getaddrinfo() is
reentrant and allows programs to eliminate IPv4-versus-IPv6 dependen‐
cies.
An example:
#include <sys/socket.h>
#include <unistd.h>
#include <stdio.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
struct sockaddr_in addr = {0};
addr.sin_family = AF_INET;
addr.sin_port = htons(80);
inet_pton(addr.sin_family, "198.252.206.16", &addr.sin_addr);
int fd = socket(addr.sin_family, SOCK_STREAM, 0);
if (fd == -1)
; /* could not create socket */
if (connect(fd, (struct sockaddr *) &addr, sizeof(addr)) == -1)
; /* could not connect */
close(fd);
}
It's difficult to tell what is being asked here. This question is ambiguous, vague, incomplete, overly broad, or rhetorical and cannot be reasonably answered in its current form. For help clarifying this question so that it can be reopened, visit the help center.
Closed 12 years ago.
The code comes from here
Given that in C++ you can use C libraries would you say that the following code is a legitimate C++ code?
If not what changes need to be applied?
This code compiles with g++ and runs as expected.
UPDATE:
Thank you for all answers. I'm still slightly confused as there's no agreement on whether or not this code comply with C++ standards. Will ask another question to dispel my doubts
UPDATE2:
To moderators who closed this question:
Just noticed that the question has been closed which I think is ridiculous. It's a down-to-earth technical question and I received down-to-earth technical answers.In case you haven't read fully the whole thread, here's the visual representation of the conclusion we've agreed on:
Clearly C++ is not a superset of C.
Closing questions that deal with coding standards is just wrong.
Client:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <netdb.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#define PORT "3490" // the port client will be connecting to
#define MAXDATASIZE 100 // max number of bytes we can get at once
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa){
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(int argc, char *argv[]){
int sockfd, numbytes;
char buf[MAXDATASIZE];
struct addrinfo hints, *servinfo, *p;
int rv;
char s[INET6_ADDRSTRLEN];
if (argc != 2) {
fprintf(stderr,"usage: client hostname\n");
exit(1);
}
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
if ((rv = getaddrinfo(argv[1], PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and connect to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("client: socket");
continue;
}
if (connect(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("client: connect");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "client: failed to connect\n");
return 2;
}
inet_ntop(p->ai_family, get_in_addr((struct sockaddr *)p->ai_addr),
s, sizeof s);
printf("client: connecting to %s\n", s);
freeaddrinfo(servinfo); // all done with this structure
if ((numbytes = recv(sockfd, buf, MAXDATASIZE-1, 0)) == -1) {
perror("recv");
exit(1);
}
buf[numbytes] = '\0';
printf("client: received '%s'\n",buf);
close(sockfd);
return 0;
}
Server:
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <errno.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <sys/wait.h>
#include <signal.h>
#define PORT "3490" // the port users will be connecting to
#define BACKLOG 10 // how many pending connections queue will hold
void sigchld_handler(int s){
while(waitpid(-1, NULL, WNOHANG) > 0);
}
// get sockaddr, IPv4 or IPv6:
void *get_in_addr(struct sockaddr *sa){
if (sa->sa_family == AF_INET) {
return &(((struct sockaddr_in*)sa)->sin_addr);
}
return &(((struct sockaddr_in6*)sa)->sin6_addr);
}
int main(void){
int sockfd, new_fd; // listen on sock_fd, new connection on new_fd
struct addrinfo hints, *servinfo, *p;
struct sockaddr_storage their_addr; // connector's address information
socklen_t sin_size;
struct sigaction sa;
int yes=1;
char s[INET6_ADDRSTRLEN];
int rv;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if ((rv = getaddrinfo(NULL, PORT, &hints, &servinfo)) != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(rv));
return 1;
}
// loop through all the results and bind to the first we can
for(p = servinfo; p != NULL; p = p->ai_next) {
if ((sockfd = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
perror("server: socket");
continue;
}
if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &yes,
sizeof(int)) == -1) {
perror("setsockopt");
exit(1);
}
if (bind(sockfd, p->ai_addr, p->ai_addrlen) == -1) {
close(sockfd);
perror("server: bind");
continue;
}
break;
}
if (p == NULL) {
fprintf(stderr, "server: failed to bind\n");
return 2;
}
freeaddrinfo(servinfo); // all done with this structure
if (listen(sockfd, BACKLOG) == -1) {
perror("listen");
exit(1);
}
sa.sa_handler = sigchld_handler; // reap all dead processes
sigemptyset(&sa.sa_mask);
sa.sa_flags = SA_RESTART;
if (sigaction(SIGCHLD, &sa, NULL) == -1) {
perror("sigaction");
exit(1);
}
printf("server: waiting for connections...\n");
while(1) { // main accept() loop
sin_size = sizeof their_addr;
new_fd = accept(sockfd, (struct sockaddr *)&their_addr, &sin_size);
if (new_fd == -1) {
perror("accept");
continue;
}
inet_ntop(their_addr.ss_family,
get_in_addr((struct sockaddr *)&their_addr),
s, sizeof s);
printf("server: got connection from %s\n", s);
if (!fork()) { // this is the child process
close(sockfd); // child doesn't need the listener
if (send(new_fd, "Hello, world!", 13, 0) == -1)
perror("send");
close(new_fd);
exit(0);
}
close(new_fd); // parent doesn't need this
}
return 0;
}
From your comments it seems like you're really interested in how portable the code is, or "how can you be sure that it will compile on any C++ compiler not just g++".
Since each compiler has s different set of extensions they support (or even a different level of how well they support the standard, or which standard they support), one way is to try compiling it with different compilers.
If you can't do that, you can specify exactly which set of extenstions and/or standards that gcc will use to compile. For example:
--std=c89
--std=c90
--std=c99
--std=gnu90 (default for C compiles)
--std=gnu99
--std=c++98
--std=c++0x
--std=gnu++98 (default for C++ compiles)
--std=gnu++0x
There are probably other, see the gcc docs for more detail: http://gcc.gnu.org/onlinedocs/gcc/Standards.html
Also, the --pedantic option can make gcc much more strict about standards compliance.
Personally I see C++ are more declarative than C which is highly procedural (though not as declarative as things like prolog).
server
ServerAction action;
Server server(action);
EventLoop loop(server);
loop.processes();
Client
Address addr("123.45.67");
Connection connect(addr);
Message message(Connection::Type::HTTP, "Plop");
connection.Send(message);
This does comply with C++ standards, and in that sense it is legally C++.
However, there is nothing here that is C++ specific. You could have just as easily compiled this with gcc.
I think what others are noting here is the fact that this code is written in a procedural way, not in an object-oriented way. Most people associate C++ with object-oriented programming, and most modern books that discuss morally responsible C++ programming would say this is a bad way to write an app. In other words, it is very much not in vogue to write programs like this when an object-oriented paradigm is available to write this sort of application in.
This application is very difficult to maintain, and is written almost haphazardly. A good C programmer would split this problem into multiple functions instead of dumping most of it in main(). It works as an example of how to do client-server, but I would hesitate to write new code like this.
You’re not writing C++, you’re taking advantage of the fact that conforming, clean C code will compile as C++ with no problems. There are some places where C++ diverges from C, but the compiler will yell at you in those cases. You could use this as a base on top of which to write some effective C++; otherwise, there’s nothing special going on.
This is valid, but not in the C++ preferred style.
For example, all the standard C libraries should be included <cstdio>, not <stdio.h>.
Another example, this code uses a #define when it could have used a constant integer.
If I were to visit you at Scotland and speak Scottish with my Portuguese accent and (short) English vocabulary ... would you say I was speaking Scottish?
Assume everybody understood me and I understood everybody :-)
Using C++, you could use better type checking features to avoid things like void*, #define, etc.
But since it does not use exclusive C features, it compiles with g++.
It is 'C' code that also conforms to the compatible subset within C++.
If it compiles it's legitimate, absent compiler bugs, but it seems to me that you have a different meaning for 'legitimate'.
I don't quite understand the question. I think you're asking whether you should just keep using it without any changes, and not worry about it - in which case I'd say yes. C++ is a superset of C - any valid C code is valid C++ code, as you see.
By convention, the standard headers have a new format -
#include <string.h>
becomes
#include <cstring>
but this isn't strictly necessary. You can't do that with the unistd and sys/ headers, anyway.
So if you're asking whether you can safely keep using it - go for it, but you may want to change errno.h to cerrno, stdio.h to cstdio, and so on.