This is some example code we used in class covering the creation of a client socket example.
DieWithMessage.c
#include <stdio.h>
#include <stdlib.h>
void DieWithUserMessage(const char *msg, const char *detail) {
fputs(msg, stderr);
fputs(": ", stderr);
fputs(detail, stderr);
fputc('\n', stderr);
exit(1);
}
void DieWithSystemMessage(const char *msg) {
perror(msg);
exit(1);
}
DieWithMessage.c
CC=g++
CFLAGS=-ggdb -std=c++11 -Wall -pedantic -Wno-sign-compare
all: client
client: TCPClient.c DieWithMessage.c
$(CC) $(CFLAGS) -o client TCPClient.c DieWithMessage.c
clean:
rm -rf client client.dSYM
Practical.h
#ifndef PRACTICAL_H_
#define PRACTICAL_H_
#include <stdbool.h>
#include <stdio.h>
#include <sys/socket.h>
// Handle error with user msg
void DieWithUserMessage(const char *msg, const char *detail);
// Handle error with sys msg
void DieWithSystemMessage(const char *msg);
// Print socket address
void PrintSocketAddress(const struct sockaddr *address, FILE *stream);
// Test socket address equality
bool SockAddrsEqual(const struct sockaddr *addr1, const struct sockaddr *addr2);// Create, bind, and listen a new TCP server socket
int SetupTCPServerSocket(const char *service);
// Accept a new TCP connection on a server socket
int AcceptTCPConnection(int servSock);
// Handle new TCP client
void HandleTCPClient(int clntSocket);
// Create and connect a new TCP client socket
int SetupTCPClientSocket(const char *server, const char *service);
enum sizeConstants {
MAXSTRINGLENGTH = 128,
BUFSIZE = 512,
};
#endif // PRACTICAL_H_
TCPClient.c
#include <assert.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <fstream>
#include <sstream>
#include <iostream>
#include "Practical.h"
using namespace std;
/* Given a sockaddr struct, return it as a string (from D&C book) */
char * get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen);
/* for reading in the test file */
class FileNotFoundException : public exception { };
string readFile(string filename);
/* a.out host port input_file */
int main(int argc, char *argv[]) {
if (argc != 3) {
DieWithUserMessage("Parameter(s)", "host port");
}
const char * host = argv[1];
const char * port = argv[2];
struct addrinfo hints, *servinfo, *p;
int rv, sock;
fprintf(stderr, "Connecting to %s:%s\n", host, port);
memset(&hints, 0, sizeof(hints));
hints.ai_family = AF_UNSPEC; // either IPv6 or IPV4 OK
hints.ai_socktype = SOCK_STREAM; // use tcp
if ((rv = getaddrinfo(host, port, &hints, &servinfo)) != 0) {
DieWithUserMessage("getaddrinfo", gai_strerror(rv));
}
for (p = servinfo; p != NULL; p = p->ai_next) {
if ((sock = socket(p->ai_family, p->ai_socktype,
p->ai_protocol)) == -1) {
DieWithUserMessage("socket", "Couldn't connect to address");
}
if (connect(sock, p->ai_addr, p->ai_addrlen) == -1) {
DieWithUserMessage("socket", "can't connect");
}
break;
}
if (p == NULL) {
DieWithUserMessage("socket", "Didn't find an address to connect to");
}
freeaddrinfo(servinfo);
char addrbuf[128];
get_ip_str(p->ai_addr, addrbuf, 128);
fprintf(stderr, "Connected to %s!\n", addrbuf);
// Receive the response
ssize_t numBytes;
do {
char buffer[BUFSIZE]; // I/O buffer
numBytes = recv(sock, buffer, BUFSIZE - 1, 0);
if (numBytes < 0)
DieWithSystemMessage("recv() failed");
else if (numBytes == 0)
break;
buffer[numBytes] = '\0'; // Terminate the string!
fputs(buffer, stdout); // Print the echo buffer
} while (numBytes > 0);
fputc('\n', stdout); // Print a final linefeed
close(sock);
fprintf(stderr, "Closed the socket!\n");
exit(0);
}
char * get_ip_str(const struct sockaddr *sa, char *s, size_t maxlen)
{
switch(sa->sa_family) {
case AF_INET:
inet_ntop(AF_INET, &(((struct sockaddr_in *)sa)->sin_addr),
s, maxlen);
break;
case AF_INET6:
inet_ntop(AF_INET6, &(((struct sockaddr_in6 *)sa)->sin6_addr),
s, maxlen);
break;
default:
strncpy(s, "Unknown AF", maxlen);
return NULL;
}
return s;
}