Commit 9a332d3d authored by Zhaozhong Liu's avatar Zhaozhong Liu
Browse files

Updates and improves tokens.c

parent ecfb5962
......@@ -24,6 +24,9 @@ upper: upper.c wrappers.o
token: token.c wrappers.o
$(CC) $(CFLAGS) -lreadline -o $@ $< wrappers.o
tokens: tokens.c wrappers.o
$(CC) $(CFLAGS) -lreadline -o $@ $< wrappers.o
.PHONY: clean
clean:
......
CC = gcc
CFLAGS = -std=gnu99 -Wall -g #-DDEBUG
LFLAGS = -lpthread -lm
EXECS = pthread_hello time_demo mergesort
all: EXECS
warppers.o: wrappers.h wrappers.c
$(CC) $(CFLAGS) -c wrappers.c wrappers.h -o wrappers.o
echod: echod.c wrappers.o
$(CC) $(CFLAGS) -o $@ $< wrappers.o $(LFLAGS)
echoreq: echoreq.c wrappers.o
$(CC) $(CFLAGS) -o $@ $< wrappers.o $(LFLAGS)
test: test.c wrappers.o
$(CC) $(CFLAGS) -o $@ $< wrappers.o $(LFLAGS)
.PHONY: clean
clean:
/bin/rm -f *.o $(EXECS)
1)That is because here we have two processes on the client and server, echoreq and echod.
The socket is used to establish communication between these two processes,
so it is a mechanism for interprocess communication.
2)The socket functionality is provided by the kernel because the kernel controls
the execution of processes by allowing their creation,
termination or suspension, and communication. Socket is for interprocess communication
so it makes sense it is provided by the kernel. Also, we know the socket function is
in section two of the manual.
3)Pipe is for communications between processes on the same computer, and
socket for communications between processes on different computers.
4)The gethostbyname() function returns a structure of type hostent for
the given host name. The hostent structure is used by functions to store
information about a given host, such as host name, IPv4 address, and so forth.
In echoreq, it convert host name to equivalent IP address and
copy to sad which is a structure to hold an IP address.
5)The getaddrinfo() function is the replecement for the obsolete gethostbyname
The getaddrinfo() combines the functionality provided by the gethostbyname(3) and
getservbyname(3) functions into a single interfaceGiven node and service, which identify an Internet host and a
service, getaddrinfo() returns one or more addrinfo structures,
each of which contains an Internet address that can be specified
in a call to bind(2) or connect(2).
/*
* CSCI 315 Operating Systems Design
* Author: L. Felipe Perrone
* Date: 2010-02-16
* Copyright (c) 2011 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual
* or institution obtaining a copy of this software and associated
* documentation files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright
* and permission notice is maintained, intact, in all copies and
* supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/uio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "wrappers.h"
#define BUFFER_SIZE 512 // length of message buffer
#define QLEN 6 // length of request queue
#define FOREVER 1
#define TRUE 1
#define FALSE 0
int num_requests = 0; // tally of client requests
/*------------------------------------------------------------------------
* Program: echod - a server for echo requests
*
* Purpose: repeatedly execute the following:
* (0) wait for a connection request from client
* (1) wait for a null-terminated string from client
* (2) send back the same string to client
* (3) close the connection
* (4) go back to step (0)
*
* Usage: echod [ port ]
*
* port - a port number in user space
*
*------------------------------------------------------------------------
*/
int
main (int argc, char* argv[]) {
struct sockaddr_in sad; // structure to hold server's address
struct sockaddr_in cad; // structure to hold client's address
int sd, sd2; // socket descriptors
int port; // protocol port number
socklen_t alen; // length of address
char in_msg[BUFFER_SIZE]; // buffer for incoming message
char *token;
char *clean_str;
// prepare address data structure
// The memset call is ESSENTIAL!
// if you don't do this every time you create a sockaddr struct, you will
// see some pretty strange behaviour
memset((char *)&sad,0,sizeof(sad)); // zero out sockaddr structure
sad.sin_family = AF_INET; // set family to Internet
sad.sin_addr.s_addr = INADDR_ANY; // set the local IP address
// verify usage
if (argc > 1) {
port = atoi(argv[1]);
}
else {
printf("Usage: %s [ port ]\n", argv[0]);
exit(-1);
}
if (port > 0)
// test for illegal value
sad.sin_port = htons((u_short)port);
else {
// print error message and exit
fprintf(stderr,"ECHOD: bad port number %s\n", argv[1]);
exit(-1);
}
// create socket
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd < 0) {
perror("ECHOD: socket creation failed");
exit(-1);
}
// assign IP/port number to socket where connections come in
if (bind(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
perror("ECHOD: bind failed");
exit(-1);
}
// set up socket to receive incomming connections
if (listen(sd, QLEN) < 0) {
perror("ECHOD: listen failed");
exit(-1);
}
// main server loop - accept and handle requests
while (FOREVER) {
alen = sizeof(cad);
if ( (sd2 = accept(sd, (struct sockaddr *)&cad, &alen)) < 0) {
perror("ECHOD: accept failed\n");
exit(-1);
}
num_requests++;
// receive the string sent by client
Recv(sd2, in_msg, BUFFER_SIZE,0);
printf("the server reads: %s\n", in_msg);
//clean up
clean_str = strtok(in_msg, " ");
while ((token = strtok(NULL, " ")) != NULL) {
strcat(clean_str, " ");
strcat(clean_str, token);
}
// send the received string back to client
Send(sd2, in_msg, BUFFER_SIZE, 0);
printf("the server sends: %s\n", in_msg);
close(sd2);
}
}
/*
* CSCI 315 Operating Systems Design
* Author: L. Felipe Perrone
* Date: 2014-09-21
* Copyright (c) 2014 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual
* or institution obtaining a copy of this software and associated
* documentation files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright
* and permission notice is maintained, intact, in all copies and
* supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "wrappers.h"
#define BUFFER_SIZE 512
#define TRUE 1
#define FALSE 0
/*------------------------------------------------------------------------
* Program: echoreq
*
* Purpose: allocate a socket, connect to a server, transfer requested
* file to local host, and print file contents to stdout
*
* Usage: echoreq [ host ] [ port ] [ string ]
*
* host - name of a computer on which server is executing
* port - protocol port number server is using
* string - a string in double quotes
*
*------------------------------------------------------------------------
*/
int
main(int argc, char* argv[]) {
struct hostent *ptrh; // pointer to a host table entr
struct sockaddr_in sad; // structure to hold an IP address
int sd; // socket descriptor
char *port; // protocol port number
char *host; // pointer to host name
char in_msg[BUFFER_SIZE]; // buffer for incoming message
int ret_val;
memset((char *)&sad,0,sizeof(sad)); // zero out sockaddr structure
sad.sin_family = AF_INET; // set family to Internet
// verify usage
if (argc < 4) {
printf("Usage: %s [ host ] [ port ] [ string ]\n", argv[0]);
exit(-1);
}
host = argv[1];
port = argv[2];
if (port > 0)
// test for legal value
sad.sin_port = htons((u_short)port);
else {
// print error message and exit
printf("ECHOREQ: bad port number %s\n", argv[2]);
exit(-1);
}
// convert host name to equivalent IP address and copy to sad
ptrh = gethostbyname(host);
if (ptrh != 0) {
printf("ECHOREQ: invalid host: %s\n", host);
exit(-1);
}
memcpy(&sad.sin_addr, ptrh->h_addr, ptrh->h_length);
// create socket
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd < 0) {
printf("ECHOREQ: socket creation failed\n");
exit(-1);
}
// connect the socket to the specified server
if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
perror("ECHOREQ: connect failed");
exit(-1);
}
// send message to server
Send(sd, argv[3], BUFFER_SIZE, 0);
printf("the client sends: %s\n", argv[3]);
// receive message echoed back by server
Recv(sd, in_msg, BUFFER_SIZE,0);
printf("the client reads: %s\n", in_msg);
printf("ECHOREQ: from server= %s\n", in_msg);
// close the socket
close(sd);
// terminate the client program gracefully
return(0);
}
/*
* CSCI 315 Operating Systems Design
* Author: L. Felipe Perrone
* Date: 2014-09-21
* Copyright (c) 2014 Bucknell University
*
* Permission is hereby granted, free of charge, to any individual
* or institution obtaining a copy of this software and associated
* documentation files (the "Software"), to use, copy, modify, and
* distribute without restriction, provided that this copyright
* and permission notice is maintained, intact, in all copies and
* supporting documentation.
*
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
* IN NO EVENT SHALL BUCKNELL UNIVERSITY BE LIABLE FOR ANY CLAIM, DAMAGES
* OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR
* OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE
* OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
*/
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "wrappers.h"
#define BUFFER_SIZE 512
#define TRUE 1
#define FALSE 0
/*------------------------------------------------------------------------
* Program: echoreq
*
* Purpose: allocate a socket, connect to a server, transfer requested
* file to local host, and print file contents to stdout
*
* Usage: echoreq [ host ] [ port ] [ string ]
*
* host - name of a computer on which server is executing
* port - protocol port number server is using
* string - a string in double quotes
*
*------------------------------------------------------------------------
*/
int
main(int argc, char* argv[]) {
//struct hostent *ptrh; // pointer to a host table entr
//structs needs for getaddrinfo():
struct addrinfo *hints;
struct addrinfo *res;
struct sockaddr_in sad; // structure to hold an IP address
int sd; // socket descriptor
char *port; // protocol port number
char *host; // pointer to host name
char in_msg[BUFFER_SIZE]; // buffer for incoming message
int ret_val;
memset((char *)&sad,0,sizeof(sad)); // zero out sockaddr structure
sad.sin_family = AF_INET; // set family to Internet
// verify usage
if (argc < 4) {
printf("Usage: %s [ host ] [ port ] [ string ]\n", argv[0]);
exit(-1);
}
host = argv[1];
port = argv[2];
if (port > 0)
// test for legal value
sad.sin_port = htons((u_short)port);
else {
// print error message and exit
printf("ECHOREQ: bad port number %s\n", argv[2]);
exit(-1);
}
// convert host name to equivalent IP address and copy to sad
// use getaddrinfo():
memset(&hints, 0, sizeof(hints));
hints->ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints->ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints->ai_flags = AI_NUMERICSERV; /* For wildcard IP address */
hints->ai_protocol = 0; /* Any protocol */
hints->ai_canonname = NULL;
hints->ai_addr = NULL;
hints->ai_next = NULL;
int result = getaddrinfo(host, port, hints, &res);
//ptrh = gethostbyname(host);
if (result != 0) {
printf("ECHOREQ: invalid host: %s\n", host);
exit(-1);
}
memcpy(&sad.sin_addr, res->ai_addr, res->ai_addrlen);
// create socket
sd = socket(PF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sd < 0) {
printf("ECHOREQ: socket creation failed\n");
exit(-1);
}
// connect the socket to the specified server
if (connect(sd, (struct sockaddr *)&sad, sizeof(sad)) < 0) {
perror("ECHOREQ: connect failed");
exit(-1);
}
// send message to server
Send(sd, argv[3], BUFFER_SIZE, 0);
printf("the client sends: %s\n", argv[3]);
// receive message echoed back by server
Recv(sd, in_msg, BUFFER_SIZE,0);
printf("the client reads: %s\n", in_msg);
printf("ECHOREQ: from server= %s\n", in_msg);
// close the socket
close(sd);
// terminate the client program gracefully
return(0);
}
p1: done
p2: done
p3: done
p4: done
answers.txt: done
#include "wrappers.h"
int Pipe(int fd[2]){
//int pipe_return = pipe(pipefd);
//if (pipe_return == -1){
if (pipe(fd) == -1){
perror("pipe failure!");
return -1; //sth went wrong
}
else{
return 0; //pipe_return should be zero if success
}
}
int Read(int fd, void *buf, size_t count){
if (read(fd, buf, count)== -1){
perror("read failuer!");
return -1;
}
return 0;
}
int Write(int fd, void *buf, size_t count){
if (write(fd, buf, count)== -1){
perror("read failuer!");
return -1;
}
return 0;
}
pid_t Fork(void){
int pid = fork();
if (-1 == pid){
perror("fork() Failure\n");
return -1;
}
else{
return pid;
}
}
int PthreadCreate(pthread_t *thread, const pthread_attr_t *attr,void *(*start_routine) (void *), void *arg){
int RET = pthread_create(thread, attr, start_routine, arg);
if (-1 == RET) {
perror("Thread failed");
exit(-1);
}
return RET;
}
int Close(int fd){
int test = close(fd);
if (-1 == test){
perror("close failuer!");
return -1;
}
else{
return 0;
}
}
int Connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen){
int test = connect(sockfd, addr, addrlen);
if (-1 == test){
perror("connect failuer!");
return -1;
}
else{
return 0;
}
}
int Bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen){
int test = bind(sockfd, addr, addrlen);
if (-1 == test){
perror("bind failuer!");
return -1;
}
else{
return 0;
}
}
int Listen(int sockfd, int backlog){
int test = Listen(sockfd,backlog);
if (-1 == test){
perror("listen failuer!");
return -1;
}
else{
return 0;
}
}
int Accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen){
int descriptor = accept(sockfd, addr, addrlen);
if (-1 == descriptor){
perror("listen failuer!");
return -1;
}
else{
return descriptor;
}
}
ssize_t Recv(int sockfd, void *buf, size_t len, int flags){
int numOfBytes = recv(sockfd, buf, len, flags);
if (-1 == numOfBytes){
perror("recv failure!");
return -1;
}
else{
return numOfBytes;
}
}
ssize_t Send(int sockfd, const void *buf, size_t len, int flags){
int numOfBytes = send(sockfd, buf, len, flags);
if (-1 == numOfBytes){
perror("send failure!");
return -1;
}
else{
return numOfBytes;
}
}
//#ifndef _WRAPPERS_H_
//#define _WRAPPERS_H_
#include <unistd.h>