Linux socket tcp通信实现

服务器端:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include

#define PORT 5678
#define MAX  10//需要监视的最大的文件描述符值+1为10

int main()
{
   int sockfd,newsockfd,fd,is_connected[MAX];
   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)
     {
       perror("socket");
       exit(1);
      }
    else
     {
       printf("socket created .\n");
       printf("socket id:%d \n",sockfd);
      }

//设置socket状态,允许在bind函数中本地地址可重复使用。
 int on=1;              
 if(setsockopt(sockfd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(int))<0)
          {
                perror("setsockopt");
                exit(1);
        }

       //添加套接字的信息,下面信息代表服务器会在端口5678和服务器所拥有的所有网卡(ip)上监听接收信息
        bzero(&addr,sizeof(addr));
        addr.sin_family=AF_INET;
        addr.sin_addr.s_addr=htonl(INADDR_ANY);
        addr.sin_port=htons(PORT);

      //绑定端口信息到新建立的socket上面
     if (bind(sockfd,(struct sockaddr*)&addr,sizeof(addr))<0)
      {
       perror("connect");
       exit(1);
      }
     else
      {
        printf("connected .\n");
        printf("local port : %d\n",PORT);
       }

    //服务器开始进行监听。3表示该进程可以入队等待的连接请求数量.
     if(listen(sockfd,3)<0)
        {
         perror("listen");
         exit(1);
        }
     else
        {
         printf("listening......\n");
        }

  //把is_connected[fd]重置为零
   for(fd=0;fd0;//置零
        }

   while(1)
       {
           FD_ZERO(&myreadfds);//清空套接字集
           FD_SET(sockfd,&myreadfds);//新加入的文件描述符,即新建的套接字,把第sockfd位置一

           for(fd=0;fdif(is_connected[fd])
              {
               FD_SET(fd,&myreadfds);
              }
            }//判断并加载上次返回的情况

                if(!select(MAX,&myreadfds,NULL,NULL,NULL))//select会更新这个集合,把其中不可读的套接字去掉
             {
              continue;
             }

   for(fd=0;fdif(FD_ISSET(fd,&myreadfds))//检查fd是否在这个集合里面
          {
           if(sockfd==fd)//检查侦听套接字和fd是否相同
            {
            if ((newsockfd=accept(sockfd,(struct sockaddr*)(&addr),&addr_len))<0)//建立通信套接字
               {
                 perror("accept");
                 exit(1);
                  }
            else
             {
               printf("accepted\n");
              }

write(newsockfd,msg,sizeof(msg));  //发送欢迎语is_connected[newsockfd]=1;//将通信套接字的位置置一
printf("connect from%s\n",inet_ntoa(addr.sin_addr));
   }

 else{
           //对可读**通信套接字**的操作                            
    bzero(msgbuffer,sizeof(msgbuffer));   //清零                            
    if(read(fd,msgbuffer,sizeof(msgbuffer))<=0) 
    {
     printf("connect closed.\n");
     is_connected[fd]=0;//不可读就从集合中删除
     close(fd);
      }
  else
    {                                      
    write(fd,msgbuffer,sizeof(msgbuffer));//发送已经接收到的东西                                           
    printf("message:%s \n",msgbuffer);

                  } } } }  }}

客户端:

#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#include 
#define PORT 5678
#define REMOTEIP "127.0.0.1"
#define   ERR_EXIT(m)  do {   perror(m); exit(EXIT_FAILURE);}  while(0) //定义出错函数

int main(int argc,char *argv[])
{
     int s;
     int addr_len=sizeof(struct sockaddr_in);
     char mybuffer[256];

  //建立套接字
  if((s=socket(AF_INET,SOCK_STREAM,0))<0)
  {
        ERR_EXIT("socket");
  }
  else
  {
        printf("socket created .\n");
        printf("socket id:%d \n",s);
  }
         struct sockaddr_in addr;
         bzero(&addr,sizeof(addr));
         addr.sin_family=AF_INET;
         addr.sin_addr.s_addr=inet_addr(REMOTEIP);
         addr.sin_port=htons(PORT);

     //请求建立连接
      if(connect(s,(struct sockaddr*)&addr,addr_len)<0)
        {
                ERR_EXIT("connect");
        }
        else
        {
                printf("connected ok!\n");
                printf("remote ip:%s\n",REMOTEIP);
                printf("remote port:%d\n",PORT);
         }

  //接收并输出欢迎语
      recv(s,mybuffer,sizeof(mybuffer),0);
      printf("%s\n",mybuffer);

 while(1)
 {
    bzero(mybuffer,sizeof(mybuffer));
    read(STDIN_FILENO,mybuffer,sizeof(mybuffer));//从键盘中读取输入的数据mybuffer
    if(write(s,mybuffer,sizeof(mybuffer))<=0)
    {//将mybuffer写入套接字
       ERR_EXIT("send");
    }
  else
   {
    bzero(mybuffer,sizeof(mybuffer));
    read(s,mybuffer,sizeof(mybuffer));
    printf("recieved:%s\n",mybuffer);
  }
  }
}

运行结果
客户端:
Linux socket tcp通信实现_第1张图片
服务器端:
Linux socket tcp通信实现_第2张图片
对select函数的详解:
select()函数以及FD_ZERO、FD_SET、FD_CLR、FD_ISSET

关于对出错函数定义使用方面有兴趣的可以参考这篇博文,讲的非常详细
#define+do{} while(0)+peeror的思考

你可能感兴趣的:(linux)