基于socket的Linux网络聊天程序--单线程非阻塞客户端

编译方式:
gcc -o chat_client chat_client.c

#include "chat.h"
#include <unistd.h>     // for fork
#include <sys/signal.h> // for signal
#include <sys/wait.h>   // for wait
#include <fcntl.h>

static char user_ID[BUFFER_SIZE];    //一个很大的缓冲区,实际ID_SIZE内有效
static char password[BUFFER_SIZE];    //一个很大的缓冲区,实际PASSWORD_SIZEE内有效
static int client_socket;


int connect_to_server(char * server_IP_addr)
{
    //设置一个socket地址结构client_addr,代表客户机internet地址, 端口
    struct sockaddr_in client_addr;
    bzero(&client_addr,sizeof(client_addr)); //把一段内存区的内容全部设置为0
    client_addr.sin_family = AF_INET;    //internet协议族
    client_addr.sin_addr.s_addr = htons(INADDR_ANY);//INADDR_ANY表示自动获取本机地址
    client_addr.sin_port = htons(0);    //0表示让系统自动分配一个空闲端口
    //创建用于internet的流协议(TCP)socket,用client_socket代表客户机socket
    client_socket = socket(AF_INET,SOCK_STREAM,0);
    if( client_socket < 0)
    {
        printf("Create Socket Failed!\n");
        return FAIL;
    }
    //把客户机的socket和客户机的socket地址结构联系起来
    if( bind(client_socket,(struct sockaddr*)&client_addr,sizeof(client_addr)))
    {
        printf("Client Bind Port Failed!\n");
        return FAIL;
    }
    //设置一个socket地址结构server_addr,代表服务器的internet地址, 端口
    struct sockaddr_in server_addr;
    bzero(&server_addr,sizeof(server_addr));
    server_addr.sin_family = AF_INET;
    if(inet_aton(server_IP_addr,&server_addr.sin_addr) == 0) //服务器的IP地址来自程序的参数
    {
        printf("Server IP Address Error!\n");
        return FAIL;
    }
    server_addr.sin_port = htons(CHAT_SERVER_PORT);
    socklen_t server_addr_length = sizeof(server_addr);
   
    //向服务器发起连接,连接成功后client_socket代表了客户机和服务器的一个socket连接
    if(connect(client_socket,(struct sockaddr*)&server_addr, server_addr_length) < 0)
    {
        printf("Can Not Connect To %s!\n",server_IP_addr);
        return FAIL;
    }
   

     return SUCCEED;
}

void send_request_to_server(signed char request, char * option, char * to, char * message)
{
    static chat_package buffer;
    bzero((char*)&buffer,BUFFER_SIZE);
    buffer.type = request;
    memcpy(buffer.from, user_ID, ID_SIZE);
    memcpy(buffer.password, password, PASSWORD_SIZE);
    if(option)
        memcpy(buffer.option, option, OPTION_SIZE);
    if(to)
        memcpy(buffer.to, to, ID_SIZE);
    if(message)
        memcpy(buffer.message, message, MESSAGE_SIZE);
    if( send(client_socket,(char*)&buffer,BUFFER_SIZE,0)<0)
    {
        printf("Socket Send Data Failed Or Closed\n");
        close(client_socket);
        exit(0);
    }
}


int receive_result_from_server(char * option, char * from, char * message)
{
    chat_package buffer;
    bzero((char*)&buffer,BUFFER_SIZE);
    int length = recv(client_socket,(char*)&buffer,BUFFER_SIZE,0);
    if(length<0)
    {
        printf("Receive Data From Server Failed\n");
    }
    if(option)
        memcpy(option, buffer.option, OPTION_SIZE);
    if(from)
        memcpy(from, buffer.from, ID_SIZE);
    if(message)
        memcpy(message, buffer.message, MESSAGE_SIZE);
    return buffer.type;       
}

int receive_result_from_server_noblock(char * option, char * from, char * message)
{
    chat_package buffer;
    bzero((char*)&buffer,BUFFER_SIZE);
       int flags = fcntl(client_socket, F_GETFL, 0);
    fcntl(client_socket, F_SETFL, flags|O_NONBLOCK);
    int length = recv(client_socket,(char*)&buffer,BUFFER_SIZE,0);
    fcntl(client_socket, F_SETFL, flags);
    if(option)
        memcpy(option, buffer.option, OPTION_SIZE);
    if(from)
        memcpy(from, buffer.from, ID_SIZE);
    if(message)
        memcpy(message, buffer.message, MESSAGE_SIZE);
    return buffer.type;       
}

void print_user_list(char * user_list_buffer)
{
    printf("\nUser_Online:\n");
    char * user_id = user_list_buffer;
    for( ; user_id<user_list_buffer+MESSAGE_SIZE; user_id+=ID_SIZE+1 )
        printf("%s\t", user_id);
    printf("\n");
}

void talk_to_server()
{
    char message_buffer[BUFFER_SIZE]; ///一个很大的缓冲区,实际MESSAGE_SIZE内有效
    bzero(message_buffer,BUFFER_SIZE);
    char receiver_user_ID[BUFFER_SIZE]; ///一个很大的缓冲区,实际ID_SIZE内有效
    bzero(receiver_user_ID,BUFFER_SIZE);
    int command_option = NO_COMMAND;
    while(command_option!=EXIT){
        printf("Command Option:\n");
        printf("%d:REGISTER\n",REGISTER);
        printf("%d:LOGIN\n",LOGIN);
        printf("%d:GET_USER_LIST\n",GET_USER_LIST);
        printf("%d:TALK_TO\n",TALK_TO);
        printf("%d:EXIT\n",EXIT);
        printf("%d:GET_MESSAGE\n",GET_MESSAGE);
        printf("Input Your Command Option Num: ");
        scanf("%d",&command_option);
        switch(command_option)
        {
        case REGISTER:
            printf("Input Your User_ID:");
            scanf("%s",user_ID);
            printf("Input Your Password:");
            scanf("%s",password);
            send_request_to_server(command_option, 0, 0, 0);
            break;
        case LOGIN:
            printf("Input Your User_ID:");
            scanf("%s",user_ID);
            printf("Input Your Password:");
            scanf("%s",password);
            send_request_to_server(command_option, 0, 0, 0);
            break;
        case GET_USER_LIST:
            send_request_to_server(command_option, USER_LIST, 0, 0);
            break;
        case TALK_TO:
            printf("Input Receiver User_ID:");
            scanf("%s",receiver_user_ID);
            printf("Write Your Message Here:");
            scanf("%s", message_buffer);           
            send_request_to_server(command_option, 0, receiver_user_ID, message_buffer);
            break;
        case EXIT:
            send_request_to_server(command_option, 0, 0, 0);
            close(client_socket);
            exit(0);
        case CHANGE:
            printf("Input Your New User_ID:");
            scanf("%s",user_ID);
            printf("Input Your New Password:");
            scanf("%s",password);
            send_request_to_server(command_option, 0, 0, 0);
        case GET_MESSAGE:
            break;
        }
        //recieve_from_server
        char option[OPTION_SIZE+1];    bzero(option,OPTION_SIZE+1);
        char message_from[ID_SIZE+1];    bzero(option,ID_SIZE+1);
        char message[MESSAGE_SIZE+1];    bzero(message,MESSAGE_SIZE+1);
        int response;
        if(GET_MESSAGE==command_option)
            response=receive_result_from_server_noblock(option, message_from, message);
        else
            response=receive_result_from_server(option, message_from, message);
        switch(response)
        {
        case FAIL:
            printf("\nRecived From Server: Failed\n");
            break;
        case SUCCEED:
            if(strcmp(option, USER_LIST)==0)
                print_user_list(message);
            else
                printf("\nRecieved From Server: OK\n");
            break;
        case TRANSFER:
            printf("\nMessage From %s :%s\n",message_from, message);
            break;
        }
    }
}

int main(int argc, char **argv)
{
    if (argc != 2)
    {
        printf("Usage: ./%s ServerIPAddress\n",argv[0]);
        exit(1);
    }
    bzero(user_ID,BUFFER_SIZE);
    bzero(password,BUFFER_SIZE);
    connect_to_server(argv[1]);
    talk_to_server();

}

posted @ 2010-12-17 14:32  flyxiang  阅读(615)  评论(0编辑  收藏  举报