I am attempting to make a game of Minesweeper where multiple players can access the server to play the game. I am struggling with using Pthreads to allow multiple connections to the game at the same time. The program starts in my main method, it then calls setup_listener then calls get_clients. I am new to pthreads and socket programming, my understanding is that for every new client added a new thread should be created. The method authenticate_process is used to check the clients username and password. Currently once i use pthread_create my game logic begins with the function menu_option passing it the current clients socket. When i run my first new client my program works perfectly however once i start a second client my program is stuck idling. Could someone please show or explain to me where/what needs to be done to fix my problem.
/* Global Variables */
int num_conn = 0;
int player_count = 0;
pthread_mutex_t mutexcount;
/*
* Main Program
*/
int main(int argc, char *argv[])
{
int port;
/* Make sure a port was specified. */
if (argc < 2) {
fprintf(stderr,"No port provided using port 12345\n");
port = 12345;
}
else {
port = atoi(argv[1]);
}
int lis_sockfd = setup_listener(port); /* Listener socket. */
pthread_mutex_init(&mutexcount, NULL);
while (1) {
int *cli_sockfd = (int*)malloc(2*sizeof(int)); /* Client sockets */
memset(cli_sockfd, 0, 2*sizeof(int));
/* Get clients connected. */
get_clients(lis_sockfd, cli_sockfd);
pthread_t thread; /* Don't really need the thread id for anything in this case, but here it is anyway. */
int result = pthread_create(&thread, NULL, menu_option, (void *)cli_sockfd); /* Start a new thread for this game. */
if (result){
printf("Thread creation failed with return code %d\n", result);
exit(-1);
}
printf("[DEBUG] New game thread started.\n");
}
close(lis_sockfd);
pthread_mutex_destroy(&mutexcount);
pthread_exit(NULL);
}
/* Sets up the listener socket. */
int setup_listener(int portno)
{
int sockfd;
struct sockaddr_in serv_addr;
/* Get a socket to listen on */
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd < 0)
error("ERROR opening listener socket.");
/* Zero out the memory for the server information */
memset(&serv_addr, 0, sizeof(serv_addr));
/* set up the server info */
serv_addr.sin_family = AF_INET;
serv_addr.sin_addr.s_addr = INADDR_ANY;
serv_addr.sin_port = htons(portno);
/* Bind the server info to the listener socket. */
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0)
error("ERROR binding listener socket.");
//printf("[DEBUG] Listener set.\n");
/* Return the socket number. */
return sockfd;
}
/* Sets up the client sockets and client connections. */
void get_clients(int lis_sockfd, int * cli_sockfd)
{
socklen_t clilen;
struct sockaddr_in serv_addr, cli_addr;
/* Listen for clients. */
listen(lis_sockfd, 253 - player_count);
/* Zero out memory for the client information. */
memset(&cli_addr, 0, sizeof(cli_addr));
clilen = sizeof(cli_addr);
/* Accept the connection from the client. */
cli_sockfd[num_conn] = accept(lis_sockfd, (struct sockaddr *) &cli_addr, &clilen);
if (cli_sockfd[num_conn] < 0)
/* Horrible things have happened. */
error("ERROR accepting a connection from a client.");
/* Send the client it's ID. */
write(cli_sockfd[num_conn], &num_conn, sizeof(int));
/* Authentication Process */
bool isauthenticated = authenticate_process(*cli_sockfd);
if (isauthenticated){
printf("Authenticated\n");
}
else {
printf("Not Authenticated\n");
}
/* Increment the player count. */
num_conn++;
pthread_mutex_lock(&mutexcount);
player_count++;
printf("Number of players is now %d.\n", player_count);
pthread_mutex_unlock(&mutexcount);
}
/* Runs a game clients. */
void *menu_option(void *thread_data)
{
int *cli_sockfd = (int*)thread_data; /* Client sockets. */
int gameoption = 0;
while(1){
gameoption = recv_int(*cli_sockfd);
printf("[DEBUG] User menu option: %d\n",gameoption);
while (gameoption == 1){
running_game(*cli_sockfd); // Run Game Logic
break;
}
while (gameoption == 2){
show_leaderboard(*cli_sockfd);
// Need to notify client to break and send menu option again
break;
}
}
printf("\nGame over.\n");
close(*cli_sockfd);
free(cli_sockfd);
pthread_exit(NULL);
}
Related
I'm trying make the program run multiple threads to it connects to different ports. I successfully made it work on a single thread but not multiple.
Below I have posted the code of what I'm using on XUbuntu.
server.c
#include <stdio.h>
#include <netdb.h>
#include <unistd.h>
#include <errno.h>
#include <stdlib.h>
#include <string.h>
// File io storing in lof file
#include "server_portLog.h"
// Thread used to create sockets
#include "sockets_pthread.h"
#define BUFFER_SIZE 1024
int main(int argc, char *argv[]) {
// Server port number
//int portNumber = atoi(argv[1]);
// sockfd: ip-address socket, newsockfd: socket from receiving client, portNum: Which port will be listening, num_bytes: received data from client
int sockfd, newsockfd, num_bytes;
// buffer: will send & receive values from the server
char buffer[BUFFER_SIZE];
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen = sizeof(cli_addr);
// Getting all ports from command line parameters and creating a socket for each
int numPorts = argc - 1;
struct port varPorts[numPorts];
pthread_t portsSockets[numPorts];
for (int i = 0; i < numPorts; i++) {
varPorts[i].portNumber = atoi(argv[i + 1]);
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_create(&portsSockets[i], &attr, createSocket, &varPorts[i]);
}
// Infinite loop too keep listening even after connection to client closes
while (1) {
// After that all the ports entered have a socket of their own the program runs them parallel together to see if any client tries to connect with one of the ports
for (int i = 0; i <= numPorts; i++) {
pthread_join(&portsSockets[i], NULL);
/* Start listening for the clients (thread blocks) */
if (listen(varPorts[i].sockfd, 5) != 0) {
printf("Error: listen() failed for port: %d \n", varPorts[i].portNumber);
//return 3;
}
// Accepting connection from client & creating socket with that client data
newsockfd = accept(varPorts[i].sockfd, (struct sockaddr *)&cli_addr, &clilen);
if (newsockfd < 0) {
printf("Error: accept() failed for port: %d \n", varPorts[i].portNumber);
//return 4;
}
/* To send receive data */
// Clearing buffer
memset(buffer, 0, BUFFER_SIZE);
// Show data received from client
num_bytes = recv(newsockfd, buffer, BUFFER_SIZE-1, 0);
if (num_bytes < 0) {
printf("Error: recv() failed for port: %d \n", varPorts[i].portNumber);
//return 5;
}
// Checking version of server if LOGFILE it creates a file to store the ports
#if defined LOGFILE
// Checking if user wrote a fileName for the logs or going to use the default log file
if (argc == 3) {
char *textFile = argv[argc-1];
serverLogFile_Custom(buffer, textFile);
}
else {
serverLogFile_Defualt(buffer);
}
#else
// Print the port numbers that connect to server
printf("Received: Client using port- %s to connect \n", buffer);
#endif
// Closing connection with client
close(newsockfd);
}
}
return 0;
}
Sockets_pthreads.h
#include <pthread.h>
struct port {
int portNumber;
int sockfd;
};
void* createSocket(void* portNumber) {
// sockfd: ip-address socket, newsockfd: socket from receiving client, portNum: Which port will be listening, num_bytes: received data from client
int sockfd, newsockfd, num_bytes;
// buffer: will send & receive values from the server
//char buffer[BUFFER_SIZE];
struct sockaddr_in serv_addr, cli_addr;
socklen_t clilen = sizeof(cli_addr);
struct port *portStruct = (struct port*) portNumber;
// Creating a new socket with ip-Protocol_tcp
// Parameters: Internet-domain, socket-stream, TCP-protocol
sockfd = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sockfd < 0) {
printf("Error: Failed to open socket for port: %d \n", portStruct->portNumber);
//return 1;
}
// Setting all bits in padding-field to 0
memset(&serv_addr, 0, sizeof(serv_addr));
// Initializing socket in sockaddr_in (stucture)
serv_addr.sin_family = AF_INET; // Seting family-Internet
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
serv_addr.sin_port = htons(portStruct->portNumber); // Setting portNum (passed in command line)
// Binding the address-structure to the socket
if (bind(sockfd, (struct sockaddr *) &serv_addr, sizeof(serv_addr)) < 0) {
printf("Error: bind() failed for port: %d \n", portStruct->portNumber);
//return 2;
}
// Geting sockfd
portStruct->sockfd = sockfd;
pthread_exit(0);
}
Problem is not clear what needs to be implemented. If various ports sockets have to accept, then it has to happen in thread function as well as recv call. In server function there are accept and recv calls which are blocking by default.
The main function should wait for connections. Upon receiving a request from the client, you create a thread that will handle this specific connection. So you will create the threads in the loop, meaning, you can theoretically have an infinite number of threads.
However, you can add a little logic to limit the number of threads that are existing at a particular time (thread pool).
So your main loop can look like this:
while (1) {
// accept: wait for a connection request
childfd = accept(parentfd, (struct sockaddr *) &clientaddr, (socklen_t *) &clientlen);
if (childfd < 0){
fprintf(stderr,"ERROR on accept");
continue;
}
hostaddrp = inet_ntoa(clientaddr.sin_addr);
if (hostaddrp == NULL){
fprintf(stderr,"ERROR on inet_ntoa\n");
continue;
}
fprintf(stdout,"server established connection with client\n");
pthread_t new_thread;
newSock = malloc(1);
*newSock = childfd;
if( pthread_create( &new_thread , NULL , server_thread , (void*) newSock) < 0){
bzero(logMsg, MAXSTRING);
sprintf(logMsg, "Thread for connection %d could not be created",childfd);
fprintf(stderr, "%s\n", logMsg);
continue;
}
fprintf(stdout, "thread created for connection %d\n", childfd);
}
The server_thread function could look like:
void *server_thread(void* clientSock){
int childfd = *(int*)clientSock;
char buf[MAXLINE]; // message buffer
int n; // message byte size
char logMsg[MAXSTRING];
size_t siz_failresp;
// read: read input string from the client
bzero(buf, MAXLINE);
n = (int) read(childfd, buf, MAXLINE);
if (n < 0){
sprintf(logMsg, "ERROR reading from socket");
fprintf(stderr,"%s", logMsg);
close(childfd);
fprintf(stdout, "Client %d disconnected \n=================\n", childfd);
//Free the socket pointer
free(clientSock);
return NULL;
}
// else, do processing of data received...
// ...................
}
There may be unused variables here above... I just got this code from one of my projects, just removing parts that do not concern you :-)
Hope it helps
I'm building a server that listens on multiple ports for multiple clients to connect to. I'm using threads to handle each of these connections. However, when > 2 clients connect to a port the server doesn't handle the following connections. Not sure if it's a connection issue or a thread issue. New to both.
/** Thread started by the client that has connected
*
*
*
*/
void* client_listener(void* client){
printf("Client for thread started\n");
fflush(stdout);
return NULL;
}
/** Listen for clients for this game
*
*
*
*/
void* listen_now(void* gameStruct){
Game* thisGame = (Game*) gameStruct;
listen(thisGame->sockfd, thisGame->totalPlayers);
int playerAdded = 0;
struct sockaddr_in cli_address;
socklen_t clilen = sizeof(cli_address);
//Keep accepting new connections
while((accept(thisGame->sockfd, (struct sockaddr*) &cli_address, &clilen) > 0)){
//Make the player in the game
printf("Total Players accepted is %d\n", playerAdded);
fflush(stdout);
//Make a client to store in the game struct
Client* thisPlayer = make_client(thisGame, thisGame->clientSockfd[thisGame->gameId]);
thisPlayer->cli_address = cli_address;
//Save values to this Client
thisPlayer->id = playerAdded;
pthread_t clientThread = thisPlayer->clientThread;
//Create thread for this client
pthread_create(&clientThread, NULL, client_listener, &thisPlayer);
playerAdded++;
}
}
/** Get the socket for the port
*
*
*/
int get_socket_for_port(Game* game, int port){
int sockfd;
sockfd = socket(AF_INET, SOCK_STREAM, 0);
game->server_address.sin_family = AF_INET;
game->server_address.sin_port = htons(port);
game->server_address.sin_addr.s_addr = INADDR_ANY;
if(bind(sockfd, (struct sockaddr*) &game->server_address, sizeof(game->server_address))<0){
printf("bind failed");
}
return sockfd;
}
/** Setup the game threads
*
*
*/
void setup_game(Server* server){
pthread_t gameThreads[server->numberOfGames-1];
Game* traversal = server->game;
int gameId;
//Loop through the games and setup their ports to listen on
while(traversal!=NULL){
traversal->clientSockfd = (int*) malloc(traversal->totalPlayers*sizeof(int));
//Get the sockfd for the port
int sockfd = get_socket_for_port(traversal, traversal->port);
//Save the socketfd for this game to struct
traversal->gameId = gameId;
traversal->sockfd = sockfd;
//Create a gameThread
pthread_create(&gameThreads[gameId], NULL, *listen_now, traversal);
gameId++;
traversal = traversal->nextGame;
}
}
When I connect 4 times to ports the server is listening on. I get the following output. Not sure, and interested in learning what might be going on.
Output:
Total Players accepted is 0
Client thread started
Total Players accepted is 1
Client thread started
Total Players accepted is 2
I have a simple C program that's supposed to listen for connections and start a new thread for each client that connects. The thread simply prints what messages it receives (for now). I followed two tutorials while making this.
It works, but I tried connecting and disconnecting repeatedly with netcat without sending any messages. Each time I connect, the program takes 8KB of memory, but it only releases 4KB when I disconnect. But I can't find the cause of the leak. It ends the thread and closes the socket every time the user disconnects. Here is all of the code involved:
void* clientFunction(void* arg) {
char receiveBuffer[RECEIVE_BUFFER_SIZE];
long receiveSize;
int clntSocket = * ((int*) arg);
while (true) {
//receive messages
receiveSize = recv(clntSocket, receiveBuffer, RECEIVE_BUFFER_SIZE, 0);
if (receiveSize <= 0) {
close(clntSocket);
return NULL;
}
printf("Received message: %s", receiveBuffer);
memset(&receiveBuffer, 0, sizeof(receiveBuffer));
}
return 0;
}
int main(int argc, const char * argv[]) {
//FOR LISTENING SOCKET =====
int servSock; /* Socket descriptor for server */
int clntSock; /* Socket descriptor for client */
struct sockaddr_in serverAddress; /* Local address */
struct sockaddr_in clientAddress; /* Client address */
unsigned int clntLen; /* Length of client address data structure */
// =======
/* Create socket for incoming connections */
if ((servSock = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
printf("Socket creation failed!\n");
return SOCKET_ERROR;
}
memset(&serverAddress, 0, sizeof(serverAddress)); /* Zero out structure */
serverAddress.sin_family = AF_INET; /* Internet address family */
serverAddress.sin_addr.s_addr = htonl(INADDR_ANY); /* Any incoming interface */
serverAddress.sin_port = htons(PORT); /* Local port */
if (bind(servSock, (struct sockaddr *) &serverAddress, sizeof(serverAddress)) < 0) {
printf("Socket binding failed!\n");
return SOCKET_ERROR;
}
if (listen(servSock, MAXPENDING) < 0) {
printf("Socket listening failed!\n");
return SOCKET_ERROR;
}
isListening = true;
int* arg = &clntSock;
while (isListening) { //should have a timer?
/* Set the size of the in-out parameter */
clntLen = sizeof(clientAddress);
/* Wait for a client to connect */
if ((clntSock = accept(servSock, (struct sockaddr *) &clientAddress, &clntLen)) >= 0) { //??????
/* clntSock is connected to a client! */
pthread_t clientThread;
pthread_create(&clientThread, NULL, &clientFunction, (void*) arg);
}
}
return 0;
}
I put in pthread_detach(pthread_self()) right after the socket closing line, and it doesn't have the problem anymore. – sudo
im writing a multithreaded server, how ever i have tried to debug this but for some reason it doesn't actually go into the client thread called by pthread_create(), bottom of main. Any idea why pthread_create() is failing ?
Also i was wondering if it would be a good idea to send a struct to the client and the client send a struct back to the server as the main communication between the server and client? or should send() and recv() be a better way to implement?
int main(int argc, char* argv[])
{
int fdServer;
int accept_fd;
int optVal = 1;
struct sockaddr_in fromAddr;
struct sockaddr_in serverAddr;
struct pollfd* pServerPollFd;
pthread_t threadId;
socklen_t fromAddrSize;
/*
* Check user input and assign values
*/
if(argc != 4)
errorServer(WRONG_CLI);
char* greeting = calloc(100,sizeof(char*));
char* file_name = calloc(100,sizeof(char*));
greeting = argv[2];
file_name = argv[3];
/*
* Check pthread_key_create != 0 -> ERROR
*/
if(pthread_key_create(&threadSpecificKey, dataDestructor))
errorServer(SYSTEM_ERROR);
int port_num = atoi(argv[1]);
if(!((port_num <= 65535)&&(1<=port_num)))
errorServer(INVALID_PORT);
/*
* Set up the server socket
*/
fdServer = socket(AF_INET, SOCK_STREAM, 0);
if(fdServer < 0)
errorServer(SYSTEM_ERROR);
if(setsockopt(fdServer, SOL_SOCKET, SO_REUSEADDR, &optVal, sizeof(int)) < 0)
errorServer(SYSTEM_ERROR);
serverAddr.sin_family = AF_INET;
serverAddr.sin_port = htons(port_num);
serverAddr.sin_addr.s_addr = htonl(INADDR_ANY);
if(bind(fdServer, (struct sockaddr*)&serverAddr, sizeof(struct sockaddr_in)) < 0)
errorServer(PORT_ERROR);
/*
* Setup poll pool
*/
pMessageBuffer = fifo_buffer_create(-1);
poll_pool* pPool = poll_pool_create(MAX_CONNECTIONS + 1);
pServerPollFd = poll_pool_allocate(pPool, fdServer);
pServerPollFd->events |= POLLIN;
int flags = fcntl(fdServer, F_GETFL);// Get the file access mode and the file status flags;
if(fcntl(fdServer, F_SETFL, flags | O_NONBLOCK) == -1)// Set the file descriptor flags to the value specified by 3rd arg.
errorServer(SYSTEM_ERROR);
if(listen(fdServer, 4) != 0)//Allow only 4 connections to the server
errorServer(SYSTEM_ERROR);
while(1) {
fromAddrSize = sizeof(struct sockaddr_in);
/* Block, waiting for a connection request to come in and accept it.
* fromAddr structure will get populated with the address of the client
*/
while((accept_fd = accept(fdServer, (struct sockaddr*)&fromAddr, &fromAddrSize)) != -1){
printf("Someone connected \n");
client_connection *pClientConnection = client_connection_create(accept_fd);
client_details *pClientDetails = client_details_create();
client_session *pClientSession = client_session_create(pClientConnection,pClientDetails);
pthread_mutex_lock(&game_state_mutex);
//SEARCH THE LINKEDLIST FOR THE GAME NAME - IF FALSE CREATE NEW LINKED ELEMENT
C_lst requestedGame;
clst_init(&requestedGame,NULL);
clst_insert_next(&requestedGame,NULL,pClientSession);
pthread_mutex_unlock(&game_state_mutex);
write(accept_fd, greeting, strlen(greeting));
/* Start a thread to deal with client communication - pass the
* connected file descriptor as the last argument.
*/
pthread_create(&threadId, NULL, client_thread, (void*)pClientSession);
pthread_detach(threadId);
}
}
free(greeting);
free(file_name);
return 0;
}
And this is the beginning of the client_thread
void * client_thread(void* arg)
{
ssize_t numBytesRead;
char buffer[MAXBUFFER];
client_session* pClientSession = (client_session*)arg;
if(pthread_setspecific(threadSpecificKey, pClientSession))
errorServer(SYSTEM_ERROR);
/* below read fails because of the nonblocking fdServer from fnctl*/
while((numBytesRead = read(fd,buffer,MAXBUFFER))>0){
//loop code here
}
Why you not checked for pthread_create return value and not print corresponding error message?
s = pthread_create(...);
if (s != 0) {
errno = s;
perror("pthread_create");
exit(EXIT_FAILURE);
}
Source: pthread_create(3)
UPD. Also, for socket setting you can try getaddrinfo(3) instead of doing all by hand: http://www.beej.us/guide/bgnet/output/html/multipage/syscalls.html#getaddrinfo
UPD 2. What do you mean by 'sending struct'?
I have a C program that I am trying to implement a daemon process that acts as a general TCP proxy server. I believe I have completed mostly everything correct but there is a while loop that I cannot figure out. Below is my code and I will put *** around what I am having trouble with.
Program descriptions
(1) The daemon listens for TCP connections on a specified port number.
(2) When a new client initiates a TCP connection request, the daemon accepts the request and
establishes a new TCP connection with the new client.
(a) The daemon forks a child process that is dedicated to handling the new client.
(b) The child process establishes a new TCP connection to a pre-assigned port on the actual
targeted server.
(c) The child process falls into a loop in which it acts as an intermediator exchanging data
(reading/writing or writing/reading) between the client and the targeted server.
(3) Once a child has been forked, the daemon process resumes listening for additional TCP
connections from other clients.
#ifndef unix
#define closesocket close
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <stdlib.h>
#include <stdio.h>
#endif
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#define PROTOPORT 5100 /* default protocol port number */
#define QLEN 6 /* size of request queue */
int visits = 0;
int argc;
char *argv[];
int main() // works as "server" side
{
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold server's address */
struct sockaddr_in cad; /* structure to hold client's address */
int sd0, sd1; /* socket descriptors */
int port; /* protocol port number */
int addrlen; /* length of address */
pid_t pid;
memset((char *)&sad, 0, sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
sad.sin_addr.s_addr = INADDR_ANY; /* set the local IP address(not specify, reserved */
if(argc > 1){
port = atoi(argv[1]);
}
else port = PROTOPORT; /* use the specified port number */
if (port > 0) /* test for illegal value */
sad.sin_port = htons((u_short)port);
else
{ /* print error message and exit */
fprintf(stderr,"bad port number %s\n", argv[1]);
exit(1);
}
/* Map TCP transport protocol name to protocol number */
if( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a socket */
sd0 = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if(sd0 < 0){
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Bind a local address to the socket */
// bind()
if (bind(sd0, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"bind failed\n");
exit(1);
}
/* Listen at the port */
// listen()
/* Specify size of request queue */
if (listen(sd0, QLEN) < 0) {
fprintf(stderr,"listen failed\n");
exit(1);
}
/* Main server loop - accept and handle requests */
while (1)
{
// accept request
addrlen = sizeof(cad);
sd1 = accept(sd0, (struct sockaddr *)&cad, &addrlen);
// fork a process
pid = fork();
if(pid == 0) // child process
{
//close oldsocket;
close(sd0);
HandleClientConnection(sd1);
break;
}
else /*parant process */
{
close(sd1);
continue;
}
}
return 0;
}
// implement "HandleClientConnection(new socket1)" - works as "client" side
HandleClientConnection(newsocket1)
{
// general socket settings at the client side
struct hostent *ptrh; /* pointer to a host table entry */
struct protoent *ptrp; /* pointer to a protocol table entry */
struct sockaddr_in sad; /* structure to hold an IP address */
int newsocket2; /* socket descriptor */
int port; /* protocol port number */
char *host; /* pointer to host name */
int n, n2; /* number of characters read */
char buf[1000]; /* buffer for data from the server */
int i;
memset((char *)&sad,0,sizeof(sad)); /* clear sockaddr structure */
sad.sin_family = AF_INET; /* set family to Internet */
***while(1) /* get the real server's IP addr from "GET" command */
{
// read to buffer and compare, such as
if(strncmp("GET", buf[i-1], 3) == 0 || strncmp("CONNECT", buf[i-1], 7) == 0)
{
while(1)
{
//...; // read more
if(strncmp("Host", buf[i-1], 4) == 0)
{
//...;
printf("\nfound the host name.\n");
//...;
}
}
break;
}
}***
/* Convert real host name to equivalent IP address and copy to sad. */
// gethostbyname();
ptrh = gethostbyname(host);
if ( ((char *)ptrh) == NULL )
{
fprintf(stderr,"invalid host: %s\n", host);
exit(1);
}
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
/* Map TCP transport protocol name to protocol number. */
if ( ((int)(ptrp = getprotobyname("tcp"))) == 0) {
fprintf(stderr, "cannot map \"tcp\" to protocol number");
exit(1);
}
/* Create a newsocket2. */
// socket();
newsocket2 = socket(PF_INET, SOCK_STREAM, ptrp->p_proto);
if (newsocket2 < 0) {
fprintf(stderr, "socket creation failed\n");
exit(1);
}
/* Connect the socket to the specified server. */
// connect()
if (connect(newsocket2, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
fprintf(stderr,"connect failed\n");
exit(1);
}
// Repeatedly read data from client (newsocket1) and write to server' side (newsocket2)
n = recv(newsocket1, buf, sizeof(buf), 0);
while (n > 0) {
write(newsocket2,buf,n);
n = recv(newsocket1, buf, sizeof(buf), 0);
}
// Repeatedly read data from server' side (newsocket2) and write to client (newsocket1).
n2 = recv(newsocket2, buf, sizeof(buf), 0);
while (n2 > 0) {
write(newsocket1,buf,n2);
n2 = recv(newsocket2, buf, sizeof(buf), 0);
}
// Close the newsocket2
close(newsocket2);
}