面向连接套接字通信实例

jackxiang 2010-8-1 23:10 | |
买了一本书:完全手册Linux系统下C程序开发详解 里面的网络tcp那块的节选,感觉不错,贴出来一下:
所谓服务器程序,指的是在网络通信时这个程序始终处于等待状态,可以接受用户的连接请求,并且对用户发送的信息进行处理,本节的实例是面向连接的套接字通信服务器程序。程序的重点是端口的监听和接收发送的信息。

代码17-7  TCP服务器程序:\源文件\17\17.25.c

#include<sys/types.h>

#include<sys/socket.h>

#include<netinet/in.h>

#include<arpa/inet.h>

#include<unistd.h>                              /*包含头文件。*/

#define PORT 5678                               /*定义端口号。*/

#define MAX 10                                  /*最多的连接数。*/

main()

{

   int sockfd,newsockfd,is_connected[MAX],fd;       /*定义相关的变量。*/

   struct sockaddr_in addr;

   int addr_len = sizeof(struct sockaddr_in);

   fd_set myreadfds;

   char msgbuffer[256];

   char msg[] ="This is the message from server.Connected.\n";

  

   if ((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)  /*建立一个socket。*/

   {

      perror("socket");

      exit(1);

   }

   else

   {

      printf("socket created .\n");              /*socket建立成功,输出提示。*/

      printf("socked id: %d \n",sockfd);

   }

  

   bzero(&addr,sizeof(addr));                   /*清空addr所在的内存。*/

   addr.sin_family =AF_INET;

   addr.sin_port = htons(PORT);

   addr.sin_addr.s_addr = htonl(INADDR_ANY);

   if(bind(sockfd,&addr,sizeof(addr))<0)    /*绑定端口。*/

   {

      perror("connect");

      exit(1);

   }

   else

   {

       printf("connected.\n");

       printf("local port:%d\n",PORT)    ;

   }

   if(listen(sockfd,3)<0)                       /*开始监听。*/

   {

      perror("listen");

      exit(1);

   }

   else

   {

      printf("listenning......\n");  

   }

   for(fd=0;fd<MAX;fd++)

   {

      is_connected[fd]=0;                        /*设置所有的标记为0。*/

   }

  

   while(1)                                 /*进入一个循环,处理所有的连接。*/

   {

      FD_ZERO(&myreadfds);                   /*清空一个标志。*/

      FD_SET(sockfd,&myreadfds);             /*设置标志。*/

      for(fd=0;fd<MAX;fd++)

      {

         if(is_connected[fd])            /*判断有没有连接。*/

         {

            FD_SET(fd,&myreadfds);            /*设置标志。*/

         }

      }

      if(!select(MAX,&myreadfds,NULL,NULL,NULL)) /*如果到达了最大的连接数则进

                                                    入下次循环。*/

      {

           continue;

      }

      for(fd=0;fd<MAX;fd++)                  /*进入一个循环。*/

      {            

         if(FD_ISSET(fd,&myreadfds))         /*判断标志。*/

         {

            if(sockfd==fd)                    /*如果新建的socket与fd相同。*/

            {

               if((newsockfd = accept (sockfd,&addr,&addr_len))<0)

                                            /*接受一个连接,新建一个socket。*/

               {

                  perror("accept");

               }

               write(newsockfd,msg,sizeof(msg));      /*给客户端发送一段信息。*/

               is_connected[newsockfd] =1;            /*设置标志。*/

               printf("cnnect from %s\n",inet_ntoa(addr.sin_addr));

                                                    /*输出客户端的IP。*/

            }

            else

            {          

               bzero(msgbuffer,sizeof(msgbuffer));    /*清空字符串。*/

               if(read(fd,msgbuffer,sizeof(msgbuffer))<=0)

                                                    /*读取结果。*/

               {

                  printf("connect closed.\n");     /*输出连接关闭。*/

                  is_connected[fd]=0;                  /*设置标志。*/

                  close(fd);                           /*关闭一个socket。*/

                }

                else

                {

                   write(fd,msgbuffer,sizeof(msgbuffer));

                                            /*发送接收到的信息。*/

                   printf("message:%s \n",msgbuffer);

                                            /*输出接收到的信息。*/

                }

             }

         }

      }

   }

}

输入下面的命令,编译这个程序。需要加-o参数指定一个输出文件名。

gcc 17.25.c -o tcpser

输入下面的命令,对这个程序添加可执行权限。

chmod +x udpcli



客户端指的是在网络通信时主动向服务器发送连接请求,主动发送信息的程序。本节将讲述面向连接的套接字通信的客户端程序。这个程序的主要内容是向服务器申请连接,并且发送用户输入的内容。

代码17-8  TCP客户端程序:\源文件\17\17.26.c

#include <stdio.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <unistd.h>

#include <fcntl.h>

#include <sys/stat.h>

#include <sys/types.h>

#include <sys/socket.h>                             /*包含头文件。*/

#define PORT 5678                                   /*定义远程端口。*/

#define REMOTE_IP "127.0.0.1"                       /*定义远程IP。*/

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

{

   int s ;                                          /*定义相关变量。*/

   struct sockaddr_in addr ;

   char mybuffer[256];

   if( (s=socket(AF_INET,SOCK_STREAM,0))<0 )    /*新建一个socket。*/

   {

      perror("socket");

      exit(1);

   }

   else

   {

      printf("socket created .\n");

      printf("socked id: %d \n",s);

   }

   bzero(&addr,sizeof(addr));                       /*设置addr。*/

   addr.sin_family =AF_INET;

   addr.sin_port=htons(PORT);

   addr.sin_addr.s_addr=inet_addr(REMOTE_IP);

   if(connect(s,&addr,sizeof(addr))<0)              /*连接远程服务器。*/

   {

      perror("connect");

      exit(1);

   }

   else

   {

      printf("connected ok!\n");

      printf("remote ip:%s\n",REMOTE_IP);

      printf("remote port:%d\n",PORT);

    }

   recv(s ,mybuffer,sizeof(mybuffer),0);        /*接收服务器发送的信息。*/

   printf("%s\n",mybuffer);                         /*输出信息。*/

   while(1)                                         /*进入一个循环。*/

   {

      bzero(mybuffer,sizeof(mybuffer));              /*清空mybuffer字符串。*/

      read(STDIN_FILENO,mybuffer,sizeof(mybuffer));  /*读取输入。*/

      if(send(s,mybuffer,sizeof(mybuffer),0)<0)      /*发送信息。*/

      {

         perror("send");                             /*错误处理。*/

         exit(1);

      }

      else

      {

         bzero(mybuffer,sizeof(mybuffer));           /*清空mybuffer内存。*/

         recv(s ,mybuffer,sizeof(mybuffer),0);       /*接收信息。*/

         printf("received:%s\n",mybuffer);           /*输出信息。*/

      }

   }

}

输入下面的命令,编译这个程序。需要加-o参数指定一个输出文件名。

gcc 17.26.c -o tcpcli

输入下面的命令,对这个程序添加可执行权限。

chmod +x udpcli



本节将对面向连接套接字通信的两个实例程序进行测试。在运行这两个程序时,需要先打开服务程序,使相应的端口处于监听状态,然后打开客户端程序,请求连接服务器的端口。

(1)输入下面的命令,运行服务器程序。

./tcpser

(2)程序的运行结果如下所示。

socket created .

socked id: 3

connected.

local port:5678

listenning......

(3)结果显示,已经建立socket,本地端口是5678。程序正在这个端口上进行监听。

(4)这时打开另一个终端,在终端中输入下面的命令,打开客户端程序。

./tcpcli

(5)程序显示的结果如下所示。结果显示程序已经建立了socket连接到了127.0.0.1这个IP上的5678号端口。服务器发送回一条信息。

socket created .

socked id: 3

connected ok!

remote ip:127.0.0.1

remote port:5678

This is the message from server.Connected.

(6)在服务器程序的终端中查看,显示的结果如下所示。

cnnect from 127.0.0.1

(7)结果表示服务器已经接受了客户端的连接请求。

(8)这时进入客户程序的终端,输入“hello”,然后按“Enter”键。显示的结果如下所示。

received:hello

(9)结果表明,程序把输入的字符串发送到了服务器,服务器又返回了这个字符串。

(10)进入到服务器的终端,可以查看到客户端发送的信息如下所示。

message:hello

(11)这两个程序进入了while循环以后,会始终执行程序无法退出。可以按“Ctrl”+“C”组合键结束程序。

作者:jackxiang@向东博客 专注WEB应用 构架之美 --- 构架之美,在于尽态极妍 | 应用之美,在于药到病除
地址:https://jackxiang.com/post/3365/
版权所有。转载时必须以链接形式注明作者和原始出处及本声明!

评论列表
发表评论

昵称

网址

电邮

打开HTML 打开UBB 打开表情 隐藏 记住我 [登入] [注册]