聊天小程序(十)增強代碼的健壯性

需求:當連接失敗、服務器拒絕連接等其他情況出現時,客戶端能正常處理並不會產生core dunp

分析:

情況一:客戶端連接服務器時,服務器拒絕未啓動 或者以啓動但拒絕連接;

情況二:客戶端創建消息處理線程時創建失敗;

暫時解決情況一;

client.c:

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

#include "base.h"

#define TRUE 1
#define PORT 5000
 
static int sockfd;
static int set_name_falg = 1;
char name[100];

void decryption(char *message);

void* recvfromserver()        //接受服務器消息線程入口函數
{
    message mess;
    int nbytes=0;
    int re;
    char mess_buf[2048];
    printf("ready to receive message!\n");
    while(1)
    {
        memset(mess_buf, 0, sizeof(mess_buf));
        nbytes = recv(sockfd, mess_buf, sizeof(mess_buf), 0);
        if(nbytes <= 0 )
            continue;
        
        memcpy(&mess, mess_buf, sizeof(mess_buf));
        decryption(mess.buffer);
        if(mess.sig_event == SIG_SET_NAME_SUCCEED)
            printf("set name succeed!\n");
        if(mess.sig_event == SIG_CLIENT_CONNECT_SUCCEED)
        {
            printf("connected succeed!, \nreceive message from server :[%s]\n", mess.buffer);

            set_name_falg = 0;  // 連接成功後,設置稱呼
        }
        if(mess.sig_event == SIG_TRASMIT_MESSAGE)
        {
            printf("[%s]",mess.buffer);
        }
        if(mess.sig_event == SIG_CLIENT_QUIT_SUCCEED)
        {
            printf("client exit succeed\n");
            break;
        }
        if(mess.sig_event == SIG_REFUSE_CLIENT_CONNECT)
        {
            printf("%s\n", mess.buffer);
            close(sockfd);
            break;
        }
    }
    pthread_exit(NULL);
    exit(0);
}

void decryption(char *message)
{
    // 對應服務端的解密方法
    int length = strlen(message);
    while(length--)
    {
        message[length] = message[length] - 1;
    }
}

int  sendMessage(char *buffer, int sig_type)
{
    int sendBytes;
    message mess;

    memset(&mess, 0, sizeof(mess));
    memcpy(mess.buffer, buffer, strlen(buffer));

    mess.sig_event = sig_type; //設置暱稱事件號
    sendBytes = send(sockfd, (char *)&mess, sizeof(mess), 0);
    if(sendBytes == -1 || sendBytes == 0)
        return 1;
    else
        return 0;
}


int main(int argc, char *argv[])
{
   char   buffer[1024];
   struct sockaddr_in server_addr;
   struct hostent *host;
   int    portnumber,nbytes;
   char   strhost[32];
   int    thr_id;         /* thread ID for the newly createdthread */
   pthread_t  p_thread;      // thread's structure     
   message mess;
   int iLoop = 5;
   if(argc!=1)
   {
		fprintf(stderr,"Usage:%s\a\n",argv[0]);
		exit(1);
   }
   snprintf(strhost, 32, "%s", "10.47.181.159");
   printf("The Server IP Address : [%s]\n", strhost);

   if((host = gethostbyname(strhost)) == NULL)
   {
		fprintf(stderr,"Gethostnameerror\n");
		exit(1);
   }
 
   /* 客戶程序開始建立 sockfd 描述符 */
   printf("Ready to Connecte the server ... ...\n");
   if((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
   {
		fprintf(stderr,"SocketError:%s\a\n",strerror(errno));
		exit(1);
   }

   /* 客戶程序填充服務端的資料 */
   bzero(&server_addr,sizeof(server_addr));
   server_addr.sin_family=AF_INET;
   server_addr.sin_port=htons(PORT);
   server_addr.sin_addr=*((struct in_addr *)host->h_addr);   
   
   /* 客戶程序發起連接請求 */
   while(iLoop--)
   {
       if(connect(sockfd,(struct sockaddr *)(&server_addr),sizeof(struct sockaddr)) == 0)
	   {
            iLoop = 5;
            break;
	   }
	   printf("reconnect the server! %d ......\n",iLoop);
	   sleep(1);
   }
   if(iLoop == -1)
   {
       printf("connect the server failed!, Error Message : [%s]\n", strerror(errno));
       exit(1);
   }
   
   /* 創建接收消息線程 */
   while(iLoop--)
   {
       if(pthread_create(&p_thread, NULL, recvfromserver, NULL) == 0)
	   {
	       iLoop = 5; // 恢復重複次數
	       break;
	   }
	   printf("recreate the thread !  %d ......\n",iLoop);
	   sleep(1);
   }
   if(iLoop == -1)
   {
       printf("create the pthread failed!, Error Message : [%s]\n", strerror(errno));
       exit(1);
   }

   printf("\nNOTICE: Press Quit or q or Q disconnect server!\n\n");
  
   while(1)
   {
       if(set_name_falg == 0)
       {
           printf("Set Your Name : ");
           gets(name);
           sendMessage(name, SIG_CLIENT_SET_NAME);
           set_name_falg = 1;
           continue;;
       }
        printf("Input message : ");
	    memset(&buffer, 0, sizeof(buffer));
        gets(buffer);
        
		if(strcmp(buffer,"Quit")==0 || strcmp(buffer,"q")==0 || strcmp(buffer,"Q")==0)
		{
		    sendMessage(buffer, SIG_CLIENT_QUIT);
			break;
		}
		if(sendMessage(buffer, SIG_TRASMIT_MESSAGE) != 0)
        {
            printf("send message error\n");
        }

	}
    close(sockfd);
    exit(0);
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章