文章详情

  • 游戏榜单
  • 软件榜单
关闭导航
热搜榜
热门下载
热门标签
php爱好者> php文档>通讯系统客户端

通讯系统客户端

时间:2009-08-25  来源:rlcpc

说明:

    该软件为自由软件,本人拥有版权,您可以自由复制,改写并且发布该软件,但是请著名版权,遵循GPL,严禁用于任何商业用途

客户端使用说明文档:
    版本1.1
    登录的用户名字符串长度在3-19之间,包含3,19,有许多标点符号和括号在登录名中被视为非法字符,将拒绝使用,合法的任意用户名都可以登录
    客户端使用了几条命令,命令的第一个字符都是'!'感叹号,假如登录上本系统的服务器,欲向对方例如Tod发送信息,首先要做的是在终端输入命令 !to Tod然后就可以向对发发送消息了,如果对方不再线或者已经退出登录在你发送消息之后会收到一条消息告知对方已经离线了.
    如果想退出客户端可以输入命令!quit,!exit或者!logout,当然输入文件结束符Ctrl+d也可以退出,有些系统终端可能不是Ctrl+d

本人英语很差,所以有些错误和警告消息可能不是很准确,请多多包含了.
为了方便,将多个文件合并成一个文件发布,后面有打包好的客户端代码归档压缩文件
  client.c

#include <unistd.h>
#include <netinet/in.h>
#include <pthread.h>
#include <sys/socket.h>
#include <sys/select.h>
#include <arpa/inet.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <errno.h>
#include <signal.h>

#define MAXSIZE 1024 //buf maximum length


#define MAXLINE 1000 //can send a message maximum length


#define TYPEBUF 1 //message types buf length


#define MINNAME 3
#define MAXNAME (MAXSIZE - MAXLINE - TYPEBUF -1 -2) //subtracting one '\n' character, two ':' characters


/* for message type */
#define LOGIN 'L'
#define SEND 'S'
#define ERROR 'E'
#define NODEF '-'

#define DEFPS "cmd> " //default Prompt string


#define EVFS ":;,/\\'\"[]{}~!@#$%^&*()" //名字中的非法字符集


#define SHOWS(s) do{\
                        printf("%s", s);\
                        fflush(stdout);\
                    } while (0)

char *
jump_chars(char* pm, const char* s)
{
    const char *ps;
    for (; *pm; ++pm) {
        for (ps = s; *ps; ps++) {
            if (*pm == *ps) break;
        }
        if (!*ps) break;
    }
    if (*pm) return(pm);
    return(0);
}

char *
tail_del_chars(char* pm, const char* s)
{
    const char *ps;
    char *p = pm;
    
    p += strlen(pm);
    for (--p; p != pm; --p) {
        for (ps = s; *ps; ps++) {
            if (*p == *ps) break;
        }
        if (!*ps) break;
    }
    if (p != pm) {
        p[1] = '\0';
        return(pm);
    }
    return(0);
}

void
del_n(char *p, int l)
{
    int len = l;
    if (l == 0) {
        len = strlen(p);
    }
    if (p[len-1] == '\n') {
        p[len-1] = '\0';
    }
    
}

/* 对数据的简单分解,返回0指示了消息格式的不正确 */
void *
msg_fj(char* pm, char **pptype, char** ppname, char** ppmsg)
{
    int n;
    char *p = pm;
    *pptype = pm;

    n = strcspn(pm, ":");
    if (n == strlen(pm)) {
        goto _err_quit;
    }
    pm += n;
    *pm = 0;
    pm++;
    *ppname = pm;

    n = strcspn(pm, ":");
    if (n == strlen(pm)) {
        goto _err_quit;
    }
    pm += n;
    *pm = 0;
    pm++;
    *ppmsg = pm;

    return(p);

_err_quit:
    *pptype = 0;
    *ppname = 0;
    *ppmsg = 0;
    return(0);
}

int
main(int argc, char *argv[])
{
    struct sockaddr_in server_addr;
    int n, port, sockfd, slctret;
    char c, *p, *pcmd, *pr;
    fd_set r_set;
    char buf[MAXSIZE], line[MAXLINE];
    char logname[MAXNAME], toname[MAXNAME], type;
    char ps[256];
    char *ptype, *pname, *pmsg;
    int len;

    if (argc != 3) {
            fprintf(stderr, "usage: %s <Ip address> <Port number>\n", argv[0]);
            exit(1);
    }

    if (inet_pton(AF_INET, argv[1], &server_addr.sin_addr.s_addr) != 1) {
        fprintf(stderr,"%s: %s: IP Address error\n", argv[0], argv[1]);
        exit(1);
    }
    c = 0;
    for (p = argv[2];*p != '\0'; p++) {
        if (*p > '9' || *p < '0') {
            c = 1;
            break;
        }
    }
    if ((port = atoi(argv[2])) <= 0 || c) {
        fprintf(stderr,"%s: %s: Port number error\n", argv[0], argv[2]);
        exit(1);
    }

    server_addr.sin_port = htons(port);
    server_addr.sin_family = AF_INET;
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        fprintf(stderr, "%s: socket error: %s\n", argv[0], strerror(errno));
        exit(1);
    }

    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) < 0) {
        fprintf(stderr, "%s: connect error: %s\n", argv[0], strerror(errno));
        exit(1);
    }

    /* set login name */
    for (;;) {
        printf("Login: ");
        fflush(stdout);
        memset(line, 0, sizeof(line));
        fgets(line, MAXLINE, stdin);
        if (strlen(line) == 0) {
            printf("\n");
            continue;
        }
        p = jump_chars(line, " \t");
        len = strlen(p);
        del_n(p, len);
        len = strlen(p);

        n = strcspn(p, EVFS);
        if (n < len) {
            printf("Login: error: User name contains the forbidden character\n");
            continue;
        }
        if (len > MAXNAME-1 || len < MINNAME) {
            printf("Login: error: User name too long or is too short, "
                "because should between %d-%d\n", MINNAME, MAXNAME-1);
            continue;
        }
        memset(logname, 0, sizeof(logname));
        strncpy(logname, p, len);
        break;
    }

    /* login to server */
    type = LOGIN;
    n = snprintf(buf, sizeof(buf), "%c:%s:", type, logname);
    if (write(sockfd, buf, n) != n) {
        fprintf(stderr, "%s: error: server closed\n", argv[0]);
        exit(1);
    }
    if ((n = read(sockfd, buf, sizeof(buf))) <= 0) {
        fprintf(stderr, "%s: error: server closed\n", argv[0]);
        exit(1);
    }
    if (msg_fj(buf, &ptype, &pname, &pmsg) == 0) {
        printf("%s: error: server exceprion datas\n", argv[0]);
        exit(1);
    }
    if (*ptype == ERROR && *pname == '\0') {
        printf("%s: error: %s\n", argv[0], pmsg);
        exit(2);
    } else if (*ptype == ERROR && *pname != '\0') {
        printf("%s: error: %s exists\n", argv[0], logname);
        exit(1);
    } else if (*ptype == LOGIN) {
        printf("%s login success\n", logname);
    } else {
        printf("%s: error: server exceprion datas\n", argv[0]);
        write(1, buf, n);
        exit(1);
    }

    memset(toname, 0, sizeof(toname));
    memset(ps, 0, sizeof(ps));
    strcpy(ps, "cmd> ");
    type = NODEF;

    for (;;) {
        SHOWS(ps);
        FD_ZERO(&r_set);
        FD_SET(STDIN_FILENO, &r_set);
        FD_SET(sockfd, &r_set);
        slctret = select(sockfd+1, &r_set, 0, 0, 0);
        if (slctret < 0) {
            fprintf(stderr, "%s: select error: %s\n", argv[0], strerror(errno));
            exit(2);
        }
        memset(buf, 0, sizeof(buf));
        if (FD_ISSET(STDIN_FILENO, &r_set)) {
            memset(line, 0, sizeof(line));
            if ((n = read(STDIN_FILENO, line, MAXLINE)) < 0) {
                fprintf(stderr, "%s: read error: %s\n", argv[0], strerror(errno));
                close(sockfd);
                exit(1);
            } else if (n == 0) {
                write(1, "\nclose client\n", strlen("\nclose client\n"));
                close(sockfd);
                exit(0);
            }
            if (line[0] == '\n') {
                continue;
            }
            p = jump_chars(line, " \t");
            del_n(line, 0);
            tail_del_chars(p, " \t");

            if (!strcmp(p, "!quit") || !strcmp(p, "!exit") || !strcmp(p, "!logout")) {
                printf("logout\n");
                exit(0);
            } else if (strstr(p, "!to") == p) {
                pcmd = p;
                p += 2;
                if (*p == '\0') {
                    printf("no parament\n");
                    continue;
                }
                *p = '\0';
                p++;
                p = jump_chars(p , "\t ");
                if (p == 0) {
                    printf("command expr error\n");
                    continue;
                }
                pr = p;
                n = strlen(pr);
                if (n > MAXNAME-1 || n < MINNAME) {
                    printf("%s: name too lang or too laa\n", pr);
                    continue;
                }
                if (strcspn(pr, EVFS) != n) {
                    printf("%s: exception user name\n", pr);
                    continue;
                }
                type = SEND;
                strcpy(toname, pr);
                snprintf(ps, sizeof(ps), "send to %s> ", toname);
                continue;
            }

            if (type == NODEF) {
                printf("what are you doing\n");
                continue;
            }
            if (toname[0] && type == SEND) {
                n = snprintf(buf, MAXSIZE, "%c:%s:%s", type, toname, line);

                /* send to server */
                if (write(sockfd, buf, n) != n) {
                    fprintf(stderr, "%s: send error: %s\n", argv[0], strerror(errno));
                    printf("%s: connect refused\n", argv[0]);
                    exit(1);
                }
                continue;
            }
            printf("error: command not found\n");
            continue;
        }
        if (FD_ISSET(sockfd, &r_set)) {
            if ((n = read(sockfd, buf, MAXSIZE)) < 0) {
                fprintf(stderr, "%s: read error: %s\n", argv[0], strerror(errno));
                exit(1);
            } else if (n == 0) {
                printf("\nserver closed, connect refused\n");
                exit(0);
            }

            if (msg_fj(buf, &ptype, &pname, &pmsg) == 0) {
                printf("%s: warning: receiving exception datas\n", argv[0]);
                /* 忽略 */
                continue;
            }
            switch (*ptype) {
            case SEND:
                printf("%s: %s\n", pname, pmsg);
                break;
            case ERROR:
                printf("Server message: %s\n", pmsg);
                if (strcmp(pname, toname) == 0) {
                    strcpy(ps, DEFPS);
                    memset(toname, 0, sizeof(toname));
                    type = NODEF;
                }
                break;
            default:
                printf("%s: error: exception datas\n", argv[0]);
                exit(2);
            }

        }

    }

    exit(0);
}
/* main end */


完整客户端代码下载:
文件: client.tar.bz2
大小: 3KB
下载: 下载
排行榜 更多 +
试着飞手游下载

试着飞手游下载

休闲益智 下载
血染小镇(功能菜单)中文版下载

血染小镇(功能菜单)中文版下载

飞行射击 下载
泰坦之旅高爆版下载

泰坦之旅高爆版下载

角色扮演 下载