2023.11.20 TIL
nc로 대신select() 함수를 사용하여 여러개의 socket을 감시serverorg.c를 수정해서 구현
#include <stdio.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <string.h>
#include <ctype.h>
#include <errno.h>
int main(int argc, char *argv[])
{
struct sockaddr_in server, remote;
int request_sock, new_sock;
int i, nfound, fd, maxfd, bytesread, addrlen;
fd_set rmask, mask;
static struct timeval timeout = {5, 0}; /* 5 seconds */
char buf[BUFSIZ];
if (argc != 2)
{
(void)fprintf(stderr, "usage: %s port\n", argv[0]);
exit(1);
}
if ((request_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0)
{
perror("socket");
exit(1);
}
memset((void *)&server, 0, sizeof server);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons((u_short)atoi(argv[1]));
if (bind(request_sock, (struct sockaddr *)&server, sizeof server) < 0)
{
perror("bind");
exit(1);
}
if (listen(request_sock, SOMAXCONN) < 0)
{
perror("listen");
exit(1);
}
FD_ZERO(&mask);
FD_SET(request_sock, &mask);
maxfd = request_sock;
for (;;)
{
rmask = mask;
nfound = select(maxfd + 1, &rmask, (fd_set *)0, (fd_set *)0, &timeout);
if (nfound < 0)
{
if (errno == EINTR)
{
printf("interrupted system call\n");
continue;
}
/* something is very wrong! */
perror("select");
exit(1);
}
if (FD_ISSET(request_sock, &rmask))
{
/* a new connection is available on the connetion socket */
addrlen = sizeof(remote);
new_sock = accept(request_sock,
(struct sockaddr *)&remote, (socklen_t *)&addrlen);
if (new_sock < 0)
{
perror("accept");
exit(1);
}
printf("connection from host %s, port %d, socket %d\n",
inet_ntoa(remote.sin_addr), ntohs(remote.sin_port),
new_sock);
FD_SET(new_sock, &mask);
if (new_sock > maxfd)
maxfd = new_sock;
FD_CLR(request_sock, &rmask);
}
for (fd = 4; fd <= maxfd; fd++)
{
/* look for other sockets that have data available */
if (FD_ISSET(fd, &rmask))
{
/* process the data */
bytesread = read(fd, buf, sizeof(buf) - 1);
if (bytesread < 0)
{
perror("read");
/* fall through */
}
if (bytesread <= 0)
{
printf("server: end of file on %d\n", fd);
FD_CLR(fd, &mask);
if (close(fd))
perror("close");
continue;
}
buf[bytesread] = '\0';
/* echo it back */
for(int cli_i = 4; cli_i < maxfd+1; cli_i++) {
if (fd == cli_i)
continue;
if (write(cli_i, buf, bytesread) != bytesread)
perror("echo");
}
}
}
}
} /* main - serverorg.c */

nc로 대신LS ext: 이 명령이 들어오면 서버는 현재 디렉토리에서 파일 확장자가 ext인 파일을 찾아서 tcp 연결을 통해 전송한다. 전송시에는 한 라인에 한 파일명을 전송한다. 구체적으로는 라인 구분을 “\r\n”으로 해서 각 파일에 대해서 “파일명\r\n”의 형태로 전송하면 된다.GET filename: 이 명령이 들어오면 서버는 filename에 해당하는 파일을 찾아서 tcp 연결을 통해 전송한다. 만약 존재하지 않으면 "FILE NOT FOUND\r\n" 을 클라이언트로 전송한다.PUT filename: 이 명령이 들어오면 서버는 filename 이라는 파일을 현재 디렉토리에 생성한 후, 이 tcp 연결을 통해명령라인이후에들어오는모든 내용을 이 filename 파일에 쓴다.Commands
./fs 100000echo "LS html" | nc localhost 10000echo "GET biga.html" | nc localhost 10000 > biga.htmlecho "PUT cli.exe" | cat - cli.exe | nc localhost 10000// Student ID : C035384
// Name : Serin Jeong
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/time.h>
#include <sys/stat.h>
#include <netinet/in.h>
#include <netdb.h>
#include <arpa/inet.h>
#include <ctype.h>
#include <errno.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <dirent.h>
int portnum = 0;
void SendFile(int new_sock, char *fname) {
char buf[BUFSIZ];
char msg[1024];
struct stat infobuf; /* place to store info */
/* get file info */
if ( stat(fname, &infobuf) == -1 ) {
/* file not found */
printf("Server Error : No such file %s!\n", fname);
sprintf(msg, "FILE NOT FOUND\r\n");
infobuf.st_size = -1;
if (write(new_sock, msg, strlen(msg))!=strlen(msg))
perror("echo error");
} else {
if(infobuf.st_size != -1) {
int s = 0;
int num = 0;
FILE *fp1 = fopen(fname, "r");
memset(buf, 0, sizeof(buf));
while((num = fread( buf, sizeof( char ), BUFSIZ - 1, fp1 )) > 0) {
s += num;
if (write(new_sock, buf, num)!= num)
perror("send file error");
}
fclose(fp1);
printf("finish %d %d\n", s, (int)infobuf.st_size);
}
}
}
void SendDir(int new_sock, char *ext) {
char buf[BUFSIZ];
DIR *folder;
struct dirent *entry;
int num = 0;
int fcnt = 0;
folder = opendir(".");
if(folder == NULL) {
perror("Unable to read directory");
return;
}
while( (entry = readdir(folder)) ) {
char *p = strrchr(entry->d_name, '.');
if(p == NULL)
continue;
if (strcmp(p + 1, ext) != 0)
continue;
sprintf(buf, "%s\n", entry->d_name);
num = strlen(buf);
if (write(new_sock, buf, num) != num) {
perror("send ls error");
}
fcnt++;
}
if (fcnt == 0) {
sprintf(buf, "FILE NOT FOUND\r\n");
num = strlen(buf);
if (write(new_sock, buf, num) != num) {
perror("send ls error");
}
}
closedir(folder);
}
void StoreFile(FILE *fp, char *fname) {
char buf[BUFSIZ];
int num = 0;
FILE *fp1 = fopen(fname, "w");
printf("fopen %s\n", fname);
if (fp1 == NULL) {
printf("fopen error for %s\n", fname);
return;
}
while((num = fread( buf, sizeof( char ), BUFSIZ - 1, fp )) > 0) {
buf[num] = 0;
printf("%s\n", buf);
if (fwrite(buf, sizeof(char), num, fp1) != num) {
printf("write error %d\n", num);
fclose(fp1);
return;
}
}
fclose(fp1);
}
int main(int argc, char *argv[]) {
struct sockaddr_in server, remote;
int request_sock, new_sock;
socklen_t addrlen;
char buf[BUFSIZ];
if (argc != 2) {
(void) fprintf(stderr,"usage: %s portnum \n",argv[0]);
exit(1);
}
portnum = atoi(argv[1]);
if ((request_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) < 0) {
perror("socket create error");
exit(1);
}
printf("Student ID : C035384\n");
printf("Name : Serin Jeong\n");
// Create a Server Socket
memset((void *) &server, 0, sizeof server);
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons((u_short)portnum);
if (bind(request_sock, (struct sockaddr *)&server, sizeof server) < 0) {
perror("bind error");
exit(1);
}
if (listen(request_sock, SOMAXCONN) < 0) {
perror("listen error");
exit(1);
}
/* a new connection is available on the connetion socket */
while(1) {
addrlen = sizeof(remote);
fflush(stdout);
new_sock = accept(request_sock,
(struct sockaddr *)&remote, &addrlen);
if (new_sock < 0) {
perror("accept error");
exit(1);
}
printf("Connection : Host IP %s, Port %d, socket %d\n",
inet_ntoa(remote.sin_addr), ntohs(remote.sin_port), new_sock);
FILE *fp = fdopen(new_sock, "r");
buf[0] = 0;
if (!fgets(buf, BUFSIZ - 1, fp)) {
printf("No Data: close connection");
fclose(fp);
if (close(new_sock)) perror("close error");
continue;
}
printf("%s", buf);
// get the request from the client
// parse the data from the client
// give the file to the client
fflush(stdout);
char *command = strtok(buf, " \t\n\r"); // Command
char *filename = strtok(NULL, " \t\n\r");
if (strcmp(command, "GET") == 0) {
SendFile(new_sock, filename);
} else if (strcmp(command, "LS") == 0) {
SendDir(new_sock, filename);
} else if (strcmp(command, "PUT") == 0) {
StoreFile(fp, filename);
} else {
printf("Unknown Command %s\n", command);
}
// fclose(fp);
if (close(new_sock))
perror("close error2");
}
}
