66666

实 验 报 告 六

(四学时)

一【实验目的】

  1. 掌握面向连接的套接字编程框架;
  2. 掌握面向无连接的套接字编程框架;
  3. 掌握I/O复用、套接字选项设置;
  4. 掌握非阻塞式I/O。

二【实验要求】

以下每个实验均要求:

  1. “实验源代码”处:粘贴所编写的程序源码,务必添加关键语句的注释
  2. “实验结果”:截图(包括编写的程序和运行结果)粘贴到“实验结果”下方,截图需看到本人的名字及学号
  3. 有“讨论”的题目,请务必认真回答;

二【实验内容】

6-1 编写一个套接字程序,要求服务器等待客户的连接请求,一旦有客户连接,服务器打印出客户端的IP地址和端口,并向客户端发送欢迎信息。

【本题比较基础,在学好课本的前提下,只需要额外学习使用书本上未提及的getpeername函数即可完成。】

【源程序】

Serve1.c:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#include <errno.h>

#include <malloc.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <sys/ioctl.h>

#include <stdarg.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#define MAXLINE 4096

int main()

{

   int listenfd,connfd;

   char ip[30]={0};

   socklen_t  clilen;

   struct sockaddr_in cliaddr,servaddr;

   listenfd=socket(AF_INET,SOCK_STREAM,0);

   bzero(&servaddr,sizeof(servaddr));

   servaddr.sin_family=AF_INET;

   servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

   servaddr.sin_port=htons(8888);

   bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

   listen(listenfd,5);

   clilen=sizeof(cliaddr);

   connfd=accept(listenfd,(struct sockaddr *)NULL,NULL);

   getpeername(connfd,(struct sockaddr *)&cliaddr,&clilen);

   inet_ntop(AF_INET,&cliaddr.sin_addr,ip,sizeof(ip));

   printf("ip:%s----port:%d\n",ip,ntohs(cliaddr.sin_port));

   printf("hello cilent");

   getchar();

   getchar();

   close(listenfd);

   return 0;

}

Client.c:

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#include <errno.h>

#include <malloc.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <sys/ioctl.h>

#include <stdarg.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#define MAXLINE 4096

int main()

{

   int sockfd;

   struct sockaddr_in servaddr;

   sockfd=socket(AF_INET,SOCK_STREAM,0);

   bzero(&servaddr,sizeof(servaddr));

   servaddr.sin_family=AF_INET;

   servaddr.sin_port=htons(8888);

   servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");

   int ret=connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

   getchar();

   getchar();

   close(sockfd);

   return 0;

}

6-2 编写一个客户端和服务器端程序,客户端连接到服务器端后,请求一个文档,然后显示结果。

【源程序】

S2ser.c:

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#include <errno.h>

#include <malloc.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <sys/ioctl.h>

#include <stdarg.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#define MAXLINE 4096

int main()

{

   int listenfd,connfd;

   char ip[30]={0};

   socklen_t  clilen;

   struct sockaddr_in cliaddr,servaddr;

   listenfd=socket(AF_INET,SOCK_STREAM,0);

   bzero(&servaddr,sizeof(servaddr));

   servaddr.sin_family=AF_INET;

   servaddr.sin_addr.s_addr=htonl(INADDR_ANY);

   servaddr.sin_port=htons(8888);

   bind(listenfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

   listen(listenfd,5);

   clilen=sizeof(cliaddr);

   connfd=accept(listenfd,(struct sockaddr *)NULL,NULL);

   getpeername(connfd,(struct sockaddr *)&cliaddr,&clilen);

   inet_ntop(AF_INET,&cliaddr.sin_addr,ip,sizeof(ip));

   char buf[100];

   read(connfd,buf,100);

   system(buf);

   close(listenfd);

   return 0;

}

S2cilent.c:

#include <unistd.h>

#include <sys/types.h>

#include <sys/socket.h>

#include <netdb.h>

#include <stdio.h>

#include <stdlib.h>

#include <string.h>

#include <ctype.h>

#include <errno.h>

#include <malloc.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <sys/ioctl.h>

#include <stdarg.h>

#include <fcntl.h>

#include <sys/types.h>

#include <sys/wait.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <signal.h>

#define MAXLINE 4096

int main()

{

   int sockfd;

   struct sockaddr_in servaddr;

   char str[100];

   sockfd=socket(AF_INET,SOCK_STREAM,0);

   bzero(&servaddr,sizeof(servaddr));

   servaddr.sin_family=AF_INET;

   servaddr.sin_port=htons(8888);

   servaddr.sin_addr.s_addr=inet_addr("127.0.0.1");

   int ret=connect(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));

   getchar();

   printf("input the order:\n");

   fgets(str,100,stdin);

   write(sockfd,str,strlen(str));

   sleep(10);

   system("cat test.txt");

   close(sockfd);

   return 0;

}

6-3编写一个基于TCP协议的网络通信程序,要求服务器通过套接字连接后,要求输入用户名,判断用户名正确后,向客户端发送连接正确的字符串,在服务器显示客户端的IP地址和端口

【源程序】

Serve.c:

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <sys/wait.h>

#include <arpa/inet.h>

#include <unistd.h>

#define MAXDATASIZE 100

#define SERVPORT 3333

#define BACKLOG 10

int main(){

      int sockfd,client_fd,recvbytes;

    char buf[MAXDATASIZE];                          //用于接收数据的缓冲区

      char user[] = "zlw";                                  //定义用户名

    struct sockaddr_in my_addr;                        //存储客户端地址

      struct sockaddr_in remote_addr;                     //存储服务端地址

    sockfd = socket(AF_INET, SOCK_STREAM, 0) ;        //建立三元组

      my_addr.sin_family = AF_INET;

      my_addr.sin_port = htons(SERVPORT);                 //获取端口号

      my_addr.sin_addr.s_addr = htonl(INADDR_ANY);

      //INADDR_ANY,转换过来就是0.0.0.0,泛指本机的意思,也就是表示本机的IP

      bzero(&(my_addr.sin_zero),8);                          //给sockfd绑定端口

      if (bind(sockfd, (struct sockaddr *)&my_addr, sizeof(struct sockaddr)) == -1){

       perror("bind error!");

         exit(1);

      }

      //sockfd设立未监听端口

      if (listen(sockfd, BACKLOG) == -1)  {

       perror("listen error!");

         exit(1);

      }

      printf("wait for accept...\n");

    while(1){

          int sin_size = sizeof(struct sockaddr_in); //等待客户端连接

          if ((client_fd = accept(sockfd, (struct sockaddr *)&remote_addr, &sin_size)) == -1) {

              perror("accept error");

                 continue;

           }

           /*每次建立完整的socket连接之后,fork一个子进程来处理与客户端的会话,父进程继续等待其他客户端的连接*/

           if (!fork()) {

              printf("accept a connection from : %s\n", inet_ntoa(remote_addr.sin_addr));

                 sleep(10);  //设置睡眠用来放大客户端同时访问的时间差

               //接收客户端信息

               if ((recvbytes = recv(client_fd, buf, MAXDATASIZE, 0)) ==-1) {

                   perror("receive error!");

                   exit(1);

              }

               buf[recvbytes] = '\0';

               //执行服务器业务逻辑并反馈信息给客户端

               if(strcmp(buf, user) == 0){

                    if (send(client_fd, "Hello,You are connected!", 26, 0) == -1){

                       perror("send error!");

                       exit(1);

                  }

               }else{

                     if (send(client_fd, "Sorry,you are not the user!", 26, 0) == -1){

                       perror("send error!");

                       exit(1);

                  }

               }

            //业务逻辑完成或关闭子进程socket连接,结束子进程

              close(client_fd);

               exit(0);

           }

           close(client_fd);       //关闭父进程socket连接

      }

}

Client.c:

#include <stdio.h>

#include <stdlib.h>

#include <errno.h>

#include <string.h>

#include <netdb.h>

#include <sys/types.h>

#include <netinet/in.h>

#include <sys/socket.h>

#include <arpa/inet.h>

#define SERVPORT 3333

#define SERVIP "0.0.0"

#define MAXDATASIZE 100

int main(int argc, char *argv[])

{

      int sockfd, recvbytes;

      char buf[MAXDATASIZE];                   //用于发送数据的缓冲区

      struct hostent *host;                    //用来接收服务主机信息

      struct sockaddr_in serv_addr;

      if (argc < 2){

        fprintf(stderr,"Please enter the username!\n");

           exit(1);

    }

      //获取服务器主机信息

      if((host=gethostbyname(SERVIP)) == NULL) {

        herror("gethostbyname error!");

           exit(1);

      }

      //建立客户端三元组

      if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1){

        perror("socket create error!");

           exit(1);

      }

      serv_addr.sin_family=AF_INET;

      serv_addr.sin_port=htons(SERVPORT);

      serv_addr.sin_addr = *((struct in_addr *)host->h_addr);

      bzero(&(serv_addr.sin_zero),8);       //置字节字符串my_addr.sin_zero的前n个字节为零且包括‘\0’

      //向服务器发送连接

    if (connect(sockfd, (struct sockaddr *)&serv_addr, sizeof(struct sockaddr)) == -1){

           perror("connect error!");

           exit(1);

      }

    //发送数据给服务器

      if (send(sockfd, argv[1], 26, 0) == -1){

        error("send error!");

        exit(0);

    }

      //接收服务器发送的信息

    if ((recvbytes=recv(sockfd, buf, MAXDATASIZE, 0)) == -1){

           perror("receive error!");

           exit(1);

      }

      buf[recvbytes] = '\0';

      //输出服务器发送的信息

      printf("information: %s\n",buf);

      close(sockfd);

}

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

m0_57872164

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值