背景

涉及Qt和数据库,是组内其他成员分工完成的.成品在GitHub
因为当时计网等还没有学到相应内容,而Linux课程设计的任务又比较急,所以,对于一些原理和函数大体了解,并未过多优化,它“能用,但还存在一些不足”。在这里,简单记录下Client端和Server端代码(不含Qt和MySQL,并未封装)。

客户端代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<netdb.h>
#include<signal.h>
#include<unistd.h>
#include<iostream>
#include<pthread.h>
#include<sys/types.h>
#include<arpa/inet.h>    
#include<sys/socket.h>
#include<netinet/in.h>
using namespace std;
char ip_address[20],mess[2222],msg_rec[2222],l_ip[20]="";
int soc_cli,soc_rec,con_rec,fin,l_len;
struct sockaddr_in  servaddr,cliaddr,localaddr;
pthread_t rcv;

void in_ip_defult()
{
  char ip_defult[]="47.94.1.16";
  stpcpy(ip_address,ip_defult);
  // the defult ip in Aliyun  
  return ;
}

void in_ip(char ip_input[])
{
  stpcpy(ip_address,ip_input);
  /* If you run the server program locally, illegal input other than the IP will still connect local successfully.
     but if run in the server,the illegal input will not successfully connect.
     ( illegal input such as:"hhh" )*/
  return ;
}

int con_ser()
{
  soc_cli=socket(AF_INET,SOCK_STREAM,0);
  // set socket | return socket description | error -1
  // AF_INET:ipv4  SOCK_STREAM:full duplex  0:automatic choose agreement of type(2)
  if(soc_cli==-1)
  {
    printf("--failed to create socket\n");
    return 0;
  }
  // init
  memset(&servaddr,0,sizeof(servaddr));
  servaddr.sin_family=AF_INET;
  // choose ipv4 but not ipv6
  servaddr.sin_port=htons(6666);
  // defult ip  port
  if(inet_pton(AF_INET,ip_address,&servaddr.sin_addr)==-1)
  {
    printf("--failed to inet_tion\n");
    return 0;
  }
  // transform the ip address to binary
  if(connect(soc_cli,(struct sockaddr*)&servaddr,sizeof(servaddr))==-1)
  //        (description,server socket address,length of socket address)
  {
    printf("--failed to connection\n");
    return 0;
  }
  //printf("--connection success!\n");
  return 1;
}

int send_info()
{
    while(1)
    {
        fgets(mess,2222,stdin);
        // buffer | stop when '\n' what want to send 
        
        if(send(soc_cli,mess,strlen(mess),0)==-1)
        // (socket description,buffer,length,0)
        {
            printf("--failed to send this  message!\n");
            return 0;
        }
        if(mess[0]=='!'&&mess[1]=='q')
        {
            /*
            close(soc_cli);
            kill(getppid(),SIGUSR1);
            exit(EXIT_SUCCESS);
            return 0;
            */
            break;
        }
    }
    close(soc_cli);
    kill(getppid(),SIGUSR1);
    exit(EXIT_SUCCESS);
//    善后工作,关闭套接字/对接父进程
    return 1;
}

void con_recv()
{
//    printf("----I'm listening the server program\n");
    while(1)
    {
        bzero(msg_rec,sizeof(msg_rec));
        // The string is zeroed out each time a message is received
        fin=read(soc_cli,msg_rec,sizeof(msg_rec));
        if(!fin)
        {
            printf("--The server program is close\n");
            break;
        }
        printf("--Msg from server:");
        fputs(msg_rec,stdout);
        printf("\n");
    }
}

int main()// 功能实现按数字标号,附注释
{
  /* 1.选择默认ip或者自定义ip,如果指向非本机的客户端,会检测ip输入是否合法*/
  in_ip_defult();
  // 默认ip,阿里云,后期调试/考核看情况去该函数里改
  /*
  scanf("%s",ip_address);
  std::cin.ignore();
  in_ip(ip_address);
  // QT选择自定义ip,传参需要 **字符数组** 形式,用指针会报错
  // 字符读入的时候需要ignore掉\n,否则会当成第一条消息发送
  */
  
  /* 2.与服务器的连接部分,返回1则连接成功,返回0则图形界面自行决定处理逻辑,这里选择退出不进行重连
  printf("--please wait to see if the connection is succeed.\n");
  printf("--you will get message in 2s if success\n");
  */
  if(!con_ser()) return 0;

  //sleep(1); 非必须,仅Shell测试时为获取成功信息时美观设置
  
  /* 3.父进程接收消息*/
  pid_t k=fork();
  if(k>0) con_recv();
  
  /* 4.子进程发送消息*/
  if(!k)
      send_info();
  close(soc_cli);
  // 关闭套接字,否则服务端陷入接收消息的死循环
  return 0;
}

服务端代码

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<netdb.h>
#include<signal.h>
#include<unistd.h>
#include<iostream>
#include<pthread.h>
#include<sys/types.h>
#include<arpa/inet.h>    
#include<sys/socket.h>
#include<netinet/in.h>
using namespace std;

int soc_ser,lst,acpt,fin,k,soc_lst,tot=0;
struct sockaddr_in seraddr,cliaddr;
char msg_rec[2222],mess[2222];
socklen_t l_size;
int clients[10],flag=-1;

int init()
{
    memset(clients,-0x3f,sizeof(clients));
    soc_ser=socket(AF_INET, SOCK_STREAM, 0);
    if(soc_ser==-1)
    {
        printf("--failed creating socket description\n");
        return 0;
    }
    l_size=sizeof(struct sockaddr_in);
    memset(&seraddr,0,sizeof(seraddr));
    seraddr.sin_family=AF_INET;
    seraddr.sin_addr.s_addr=htonl(INADDR_ANY);
    seraddr.sin_port=htons(6666);
    if(bind(soc_ser,(struct sockaddr*)&seraddr,sizeof(seraddr))==-1)
    {
        printf("--failed bind\n");
        return 0;
    }
    lst=listen(soc_ser,10);
    if(lst==-1)
    {
        printf("--failed listen\n");
        return 0;
    }
    printf("--Listen success,now begin accept:\n");
    return 1;
}

void *ser_rcv(void *q)
{
    fin=0;
    k=*(int *)q;
    bzero(msg_rec,sizeof(msg_rec));
    while(read(k,msg_rec,sizeof(msg_rec))&&strlen(msg_rec))
    // 如果读入失败,字符数组清零,连'\0'都没有,踩坑好久
    {
        // The string is zeroed out each time a message is received
        if(msg_rec[0]=='!'&&msg_rec[1]=='q')
        {
            tot--;
            break;
        }
        else
        {
            if(msg_rec)
            printf("--messages from clients: ");
            fputs(msg_rec,stdout);
            printf("\n");
            for(int i=0;i<10;i++)
            {
                if(clients[i]!=-0x3f)
                {
                    stpcpy(mess,msg_rec);
                    send(clients[i], mess, strlen(mess), 0);
                }
            }
            bzero(msg_rec,sizeof(msg_rec));
        }
    }
    for(int i=0;i<10;i++)
    {
        if(clients[i]==k)
        {
            clients[i]=-0x3f;
            break;
        }
    }
    return 0;
}
int main()
{
    if(!init())
      return 1;
    while(1)
    {
        acpt=accept(soc_ser,(struct sockaddr *)&cliaddr,&l_size);
        if(acpt!=-1)
        {
            tot++;
            if(tot>10)
            {
                tot--;
                break;
            }
            while(1)
            {
                ++flag;
                if(flag>9) flag-=10;
                if(clients[flag]!=-0x3f)
                {
                    clients[flag]=acpt;
                    break;
                }
            }
            pthread_t k;
            pthread_create(&k,NULL,ser_rcv,&acpt);
        }
    }
    return 0;
}
最后修改:2022 年 01 月 11 日
如果觉得我的文章对你有用,请随意赞赏