实验四 Web服务器1-socket编程

基于华为鲲鹏云服务器CentOS中(或Ubuntu),使用Linux Socket实现:
1. time服务器的客户端服务器,提交程序运行截图
代码:

//timeclient.c
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#define RIO_BUFSIZE 8192

typedef struct{
int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[RIO_BUFSIZE];

}rio_t;

#define MAXLINE 200

typedef struct sockaddr SA;

int open_clientfd(char * hostname, int port)
{
int clientfd;
struct hostent *hp;
struct sockaddr_in serveraddr;

/* Create a socket discriptor */
if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "socket error: %s\n", (char *)strerror(errno));
return -1;
}

/* Fill in the server’s IP address and port */
if ((hp = gethostbyname(hostname)) == NULL) {
fprintf(stderr, "gethostbyname error: %s\n", (char *) strerror(errno));
close(clientfd);
return -2;
}
bzero((char *)&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)hp->h_addr,
(char *)&serveraddr.sin_addr.s_addr, hp->h_length);
serveraddr.sin_port = htons((unsigned short)port);

/* Establish a connection with the server */
if (connect(clientfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0) {
fprintf(stderr, "connect error: %s\n", (char *) strerror(errno));
close(clientfd);
return -1;
}

return clientfd;
}

int main(int argc,char **argv)
{
int clientfd,port;
char *cport;
char *host,buf[MAXLINE];
char sbuf[MAXLINE];
char rbuf[MAXLINE];
rio_t rio;
char str1[MAXLINE]="客户端IP:";
char str2[MAXLINE]="学号:20201202";
char str3[MAXLINE]="当地时间:";
if(argc!=3)
{
fprintf(stderr,"usage:%s <host> <port>\n",argv[0]);
exit(0);
}
host = argv[1];
port = atoi(argv[2]);
clientfd = open_clientfd(host,port);
while(1)
{
recv(clientfd,rbuf,MAXLINE,0);
printf("%s",str1);
puts(host);
printf("%s",str2);
putchar('\n');
printf("%s",str3);
puts(rbuf);
close(clientfd);
exit(0);
}
}

 

// timeserver.c
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <errno.h>

#define MAXLINE 200
#define RIO_BUFSIZE 8192

typedef struct
{
int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[RIO_BUFSIZE];

} rio_t;

typedef struct sockaddr SA;

typedef struct
{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
} tm;

void sigchld_handler(int sig)
{
pid_t pid;
int stat;
while ((pid = waitpid(-1, &stat, WNOHANG)) > 0)
{
printf("child %d terminated\n", pid);
}
return;
}

#define LISTENQ 1024
typedef struct sockaddr SA;

int open_listenfd(int port)
{
int listenfd, optval = 1;
struct sockaddr_in serveraddr;

/* Create a socket discriptor */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "socket error: %s\n", (char *) strerror(errno));
return -1;
}

/* Eliminates "Addrss already in use" error from bind */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval, sizeof(int)) < 0) {
fprintf(stderr, "setsockopt error: %s\n", (char *) strerror(errno));
goto err_out;
}

/* Listenfd will be an endpoint for all requests to port
on any IP address for this host */
bzero((char *)&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);

if (bind(listenfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0) {
fprintf(stderr, "bind error: %s\n", (char *) strerror(errno));
goto err_out;
}

/* Make it a listening socket ready to accept connection request */
if (listen(listenfd, LISTENQ) < 0) {
fprintf(stderr, "listen error: %s\n", (char *) strerror(errno));
goto err_out;
}
return listenfd;

err_out:
close(listenfd);
return -1;
}

int main(int argc, char **argv)
{
int listenfd, connfd, port, clientlen;
char *cport;
struct sockaddr_in clientaddr;
struct hostent *hp;
char *haddrp;
char sbuf[MAXLINE];
char rbuf[MAXLINE];
rio_t rio;
time_t lt;
tm *local;
char str1[MAXLINE] = "客户端IP:";
char str2[MAXLINE] = "服务器实现者学号:";
char str3[MAXLINE] = "当地时间:";
if (argc != 2)
{
fprintf(stderr, "usage:%s <port>\n", argv[0]);
exit(0);
}
port = atoi(argv[1]);
signal(SIGCHLD, sigchld_handler);
listenfd = open_listenfd(port);
while (1)
{
clientlen = sizeof(clientaddr);
connfd = accept(listenfd, (SA *)&clientaddr, &clientlen);
hp = gethostbyaddr((const char *)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr), AF_INET);
haddrp = inet_ntoa(clientaddr.sin_addr);
printf("server connected to %s (%s)\n", hp->h_name, haddrp);
if (fork() == 0)
{
close(listenfd);
lt = time(NULL);
local = localtime(&lt);
strftime(sbuf, 64, "%Y-%m-%d %H:%M:%S", local);
send(connfd, sbuf, MAXLINE, 0);
close(connfd);
exit(0);
}
close(connfd);
}
}

 

运行截图:

 

2. echo服务器的客户端服务器,提交程序运行截图,服务器把客户端传进来的内容加入“服务器进程pid  你的学号 姓名 echo :”返回给客户端
代码:

//echoserver.c
#include <stdio.h>
#include <unistd.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/wait.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <time.h>
#include <string.h>
#include <pthread.h>
#include <errno.h>

#define LISTENQ 1024
#define MAXLINE 200
#define RIO_BUFSIZE 8192

typedef struct{
int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[RIO_BUFSIZE];

}rio_t;

typedef struct sockaddr SA;

typedef struct{
int tm_sec;
int tm_min;
int tm_hour;
int tm_mday;
int tm_mon;
int tm_year;
int tm_wday;
int tm_yday;
int tm_isdst;
}tm;


void *thread(void *vargp);

int open_listenfd(int port)
{
int listenfd, optval = 1;
struct sockaddr_in serveraddr;

/* Create a socket discriptor */
if ((listenfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "socket error: %s\n", (char *) strerror(errno));
return -1;
}

/* Eliminates "Addrss already in use" error from bind */
if (setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR,
(const void *)&optval, sizeof(int)) < 0) {
fprintf(stderr, "setsockopt error: %s\n", (char *) strerror(errno));
goto err_out;
}

/* Listenfd will be an endpoint for all requests to port
on any IP address for this host */
bzero((char *)&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
serveraddr.sin_addr.s_addr = htonl(INADDR_ANY);
serveraddr.sin_port = htons((unsigned short)port);

if (bind(listenfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0) {
fprintf(stderr, "bind error: %s\n", (char *) strerror(errno));
goto err_out;
}

/* Make it a listening socket ready to accept connection request */
if (listen(listenfd, LISTENQ) < 0) {
fprintf(stderr, "listen error: %s\n", (char *) strerror(errno));
goto err_out;
}
return listenfd;

err_out:
close(listenfd);
return -1;
}

int main(int argc,char **argv){

int listenfd,*connfdp,port;
int clientlen;
struct sockaddr_in clientaddr;
struct hostent *hp;
char *haddrp;
pthread_t tid;

if(argc != 2){

fprintf(stderr,"usage:%s <port>\n",argv[0]);
exit(0);
}

port = atoi(argv[1]);

listenfd = open_listenfd(port);


while(1){

clientlen = sizeof(clientaddr);

connfdp =malloc(sizeof(int));

*connfdp = accept(listenfd,(SA *)&clientaddr,&clientlen);


hp = gethostbyaddr((const char*)&clientaddr.sin_addr.s_addr,
sizeof(clientaddr.sin_addr.s_addr),AF_INET);

haddrp = inet_ntoa(clientaddr.sin_addr);

printf("server connected to %s (%s)\n",hp->h_name,haddrp);

pthread_create(&tid,NULL,thread,connfdp);

pthread_join(tid,NULL);
}
}


void *thread(void *vargp){

time_t lt;
tm *local;
char sbuf[MAXLINE];
char rbuf[MAXLINE];
int connfd = *((int*)vargp);

free(vargp);

pthread_detach(pthread_self());

recv(connfd,rbuf,MAXLINE,0);
printf("The massage is :%s\n",rbuf);
send(connfd,rbuf,MAXLINE,0);

close(connfd);

return NULL;
}

#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>

#define RIO_BUFSIZE 8192

typedef struct{
int rio_fd;
int rio_cnt;
char *rio_bufptr;
char rio_buf[RIO_BUFSIZE];

}rio_t;

#define MAXLINE 200

typedef struct sockaddr SA;

int open_clientfd(char * hostname, int port)
{
int clientfd;
struct hostent *hp;
struct sockaddr_in serveraddr;

/* Create a socket discriptor */
if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
fprintf(stderr, "socket error: %s\n", (char *)strerror(errno));
return -1;
}

/* Fill in the server’s IP address and port */
if ((hp = gethostbyname(hostname)) == NULL) {
fprintf(stderr, "gethostbyname error: %s\n", (char *) strerror(errno));
close(clientfd);
return -2;
}
bzero((char *)&serveraddr, sizeof(serveraddr));
serveraddr.sin_family = AF_INET;
bcopy((char *)hp->h_addr,
(char *)&serveraddr.sin_addr.s_addr, hp->h_length);
serveraddr.sin_port = htons((unsigned short)port);

/* Establish a connection with the server */
if (connect(clientfd, (SA *)&serveraddr, sizeof(serveraddr)) < 0) {
fprintf(stderr, "connect error: %s\n", (char *) strerror(errno));
close(clientfd);
return -1;
}

return clientfd;
}

int main(int argc,char **argv){

int clientfd,port;
char *host,buf[MAXLINE];
char sbuf[MAXLINE];
char rbuf[MAXLINE];
rio_t rio;
char str1[MAXLINE]="服务器进程pid:";
char str2[MAXLINE]="学号姓名:20201202史婧怡";

char str3[MAXLINE]="echo:";

if(argc!=3){

fprintf(stderr,"usage:%s <host> <port>\n",argv[0]);
exit(0);
}
host = argv[1];
port = atoi(argv[2]);

clientfd = open_clientfd(host,port);

while(1){
scanf("%[^\n]",sbuf);
send(clientfd,sbuf,MAXLINE,0);

recv(clientfd,rbuf,MAXLINE,0);

printf("%s",str1);
printf("%d\n",getpid());

printf("%s",str2);
putchar('\n');

printf("%s",str3);

puts(rbuf);

close(clientfd);

exit(0);
}

}

运行截图:

 

3. 服务器部署到华为云服务器,客户端用Ubuntu虚拟机。 4. 要用多线程或者多进程实现,至少连接两个客户端。
运行截图:

 

 


posted @ 2022-11-30 14:53  20201202史婧怡  阅读(40)  评论(0编辑  收藏  举报