需求:當連接失敗、服務器拒絕連接等其他情況出現時,客戶端能正常處理並不會產生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);
}