jchat:linux聊天程序4:客户端

makefile:

jchat:        main.o login.o regist.o tcp.o
    gcc -w main.o login.o regist.o tcp.o -o jchat
    rm -f *.o *.gch *~
main.o:        main.c login.h regist.h tcp.h
    gcc -w -c main.c login.h regist.h tcp.h
login.o:    login.c login.h tcp.h
    gcc -w -c login.c login.h tcp.h
regist.o:    regist.c regist.h tcp.h
    gcc -w -c regist.c regist.h tcp.h
tcp.o:        tcp.c tcp.h
    gcc -w -c tcp.c tcp.h

clean:
    rm -f *.o *.gch *~ jchat

main.c:

/*client/main.c*/

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>

#include "login.h"
#include "regist.h"
#include "tcp.h"

#define MAXLINE 4096
#define IP "127.0.0.1" // localhost
#define PORT 12345

char sendbuff[MAXLINE], recvbuff[MAXLINE];//send buffer & recv buffer
int sockfd;//socket file descriptor

int main(int argc, char *argv[])
{
    if ((sockfd = link_server(IP, PORT)) == -1) {
        exit(1);
    }

    char choice[107];
    while (1) {
        printf("login or regist:");
        scanf("%s", choice);
        if (strcmp(choice, "login") == 0) {
            login(sockfd);
        }
        else if (strcmp(choice, "regist") == 0) {
            regist(sockfd);
        }
        else {
            puts("input login or regist!");
        }
    }
}

login.c:登录操作

/*client/login.c*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#include "login.h"
#include "tcp.h"

#define MAXLINE 4096
#define IP "127.0.0.1" // localhost
#define PORT 12345

char user[107], passwd[107];
char line[107];

/*
 * login to server
 * return 1 if succeed, 0 if fail
 */
int login_succeed(int sockfd)
{
    char sendbuff[MAXLINE], recvbuff[MAXLINE];
    sprintf(sendbuff, "l:%s:%s", user, passwd);

    write(sockfd, sendbuff, strlen(sendbuff));
    //printf("sendbuff> ‘%s‘\n", sendbuff);
    int n = read(sockfd, recvbuff, MAXLINE);
    recvbuff[n] = ‘\0‘;
    //printf("recvbuff> ‘%s‘\n", recvbuff);

    if (strcmp(recvbuff, "y") == 0) return 1;
    else return 0;
}

/*
 * send message to another user by server
 */
void send_mesg(int sockfd)
{
    char sendbuff[MAXLINE];
    int len = strlen(line);
    int i = 1, j, k, pos;

    while (i<len && (line[i]==‘ ‘ || line[i]==‘\t‘)) ++i;
    j = i + 1;
    while (j<len && line[j]!=‘ ‘ && line[j]!=‘\t‘) ++j;
    k = j + 1;
    while (k<len && (line[k]==‘ ‘ || line[k]==‘\t‘)) ++k;

    int send_len = 2, ulen = strlen(user);
    sendbuff[0] = ‘s‘;sendbuff[1] = ‘:‘;
    for (pos=0; pos<ulen; ++pos) sendbuff[send_len++] = user[pos];
    sendbuff[send_len++] = ‘:‘;
    for (pos=i; pos<j; ++pos) sendbuff[send_len++] = line[pos];
    sendbuff[send_len++] = ‘:‘;
    for (pos=k; pos<len; ++pos) sendbuff[send_len++] = line[pos];
    sendbuff[send_len++] = ‘\0‘;

    write(sockfd, sendbuff, strlen(sendbuff));
    //printf("send_mesg sendbuff> ‘%s‘\n", sendbuff);
}

/*
 * ask the server the online user
 */
void check_online(int sockfd)
{
    char sendbuff[MAXLINE], recvbuff[MAXLINE];
    sprintf(sendbuff, "o");

    write(sockfd, sendbuff, strlen(sendbuff));
    //printf("check_online sendbuff> ‘%s‘\n", sendbuff);
    int recv_len = read(sockfd, recvbuff, MAXLINE);
    recvbuff[recv_len] = ‘\0‘;
    //printf("check_online recvbuff> ‘%s‘\n", recvbuff);

    if (recv_len <= 1) {
        printf("no one online\n");
    }
    else {
        int i = 0, j, k, num = 0;
        char on[100][21];
        while (i < recv_len) {
            j = i+1;
            while (recvbuff[j] != ‘;‘) ++j;
            for (k=i; k<j; ++k) on[num][k-i] = recvbuff[k];
            on[num][j-i] = ‘\0‘;
            ++num;
            i = j + 1;
        }
        printf("%d online user:\n", num);
        for (k=0; k<num; ++k) printf("  %s\n", on[k]);
    }
}

/*
 * quit this client
 * quit the process fork by server
 */
void quit(int sockfd)
{
    char sendbuff[MAXLINE];
    sprintf(sendbuff, "q:%s", user);

    write(sockfd, sendbuff, strlen(sendbuff));
    //printf("quit sendbuff> ‘%s‘\n", sendbuff);
}

/*
 * get unread message from server every 1 second
 */
void get_mesg(int sockfd)
{
    char sendbuff[MAXLINE], recvbuff[MAXLINE];

    while (1) {
        sleep(1);

        sprintf(sendbuff, "g:%s", user);
        write(sockfd, sendbuff, strlen(sendbuff));

        //printf("get_mesg sendbuff> ‘%s‘\n", sendbuff);
        int recv_len = read(sockfd, recvbuff, MAXLINE);
        recvbuff[recv_len] = ‘\0‘;
        //printf("get_mesg recvbuff> ‘%s‘\n", recvbuff);

        if (recv_len <= 1) { // no message get
            continue;
        }

        int num, i, j, k, l;
        num = i = 0;
        char on[100][21];
        while (i < recv_len) {
            j = i + 1;
            while (recvbuff[j] != ‘;‘) ++j;

            k = i;
            while (k<j && recvbuff[k]!=‘:‘) ++k;
            int line_len = 0;
            for (l=i; l<k; ++l) line[line_len++] = recvbuff[l];
            line[line_len++] = ‘:‘;line[line_len++] = ‘ ‘;
            for (l=k+1; l<j; ++l) line[line_len++] = recvbuff[l];
            line[line_len] = ‘\0‘;
            puts(line);

            i = j + 1;
        }
    }
}

/*
 * send online notice to server every 5 seconds
 */
void online_notice(int sockfd)
{
    char sendbuff[MAXLINE];

    while (1) {
        sprintf(sendbuff, "a:%s", user);

        write(sockfd, sendbuff, strlen(sendbuff));
        //printf("sendbuff> ‘%s‘\n", sendbuff);

        sleep(5);
    }
}

/*
 * everything after login
 * thread 1 : receive user command
 * thread 2 : get unread message from server
 * thread 3 : send online notice to server
 */
void login(int sockfd)
{
    printf("user: ");
    scanf("%s", user);
    printf("password: ");
    scanf("%s", passwd);

    if (login_succeed(sockfd)) {
        printf("welcome %s~\n", user);
        pid_t pid1 = fork();
        if (pid1 != 0) {
            pid_t pid2 = fork();
            if (pid2 != 0) { // thread 1 : input command
                while (gets(line)) {
                    switch (line[0]) {
                        case ‘s‘: // send message
                            send_mesg(sockfd);
                            break;
                        case ‘o‘: // check online
                            check_online(sockfd);
                            break;
                        case ‘q‘: // quit
                            quit(sockfd);
                            kill(pid1, 9);
                            kill(pid2, 9);
                            printf("goobye %s ~\n", user);
                            exit(0);
                            break;
                    }
                }
            }
            else { // thread 2 : get message from server
                get_mesg(sockfd);
            }
        }
        else { // thread 3 : send online notice
            online_notice(sockfd);
        }
    }
    else {
        printf("login failed\n");
    }
}

login.h:

/*client/login.h*/

#ifndef LOGIN_H
#define LOGIN_H

void login(int sockfd);

#endif // LOGIN_H

regist.c:注册操作

/*client/regist.c*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>

#include "regist.h"
#include "tcp.h"

#define MAXLINE 4096

extern char sendbuff[MAXLINE], recvbuff[MAXLINE];
char user[107], passwd[107];

/*
 * regist new user
 * return 1 if succeed, 0 if fail
 */
int regist_succeed(int sockfd)
{
    sprintf(sendbuff, "r:%s:%s", user, passwd);

    write(sockfd, sendbuff, strlen(sendbuff));
    int n = read(sockfd, recvbuff, MAXLINE);
    recvbuff[n] = 0;

    if (strcmp(recvbuff, "y") == 0) return 1;
    else return 0;
}

/*
 * regist
 */
void regist(int sockfd)
{
    printf("user: ");
    scanf("%s", user);
    printf("password: ");
    scanf("%s", passwd);

    if (regist_succeed(sockfd)) {
        printf("regist a new user!\n");
    }
    else {
        printf("fail in regist new user!\n");
    }
}

regist.h:

/*client/regist.h*/

#ifndef REGIST_H
#define REGIST_H

void regist(int sockfd);

#endif // REGIST_H

tcp.c:建立与服务器的连接

/*client/tcp.c*/

#include <stdio.h>
#include <unistd.h>
#include <string.h>
#include <stdlib.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <sys/un.h>
#include <netinet/in.h>

#include "tcp.h"

/*
 * link to assign IP and port
 * return the socket file descriptor
 */
int link_server(char *IP, int port)
{
    int sockfd;
    struct sockaddr_in servaddr;

    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) {
        fprintf(stderr, "socket error\n");
        return -1;
    }

    memset(&servaddr, 0, sizeof(servaddr));
    servaddr.sin_family = AF_INET;
    servaddr.sin_port = htons(port);
    if (inet_pton(AF_INET, IP, &servaddr.sin_addr) <= 0) {
        fprintf(stderr, "inet_pton error for %s\n", IP);
        return -1;
    }

    if (connect(sockfd, (struct sockaddr *) &servaddr, sizeof(servaddr)) < 0) {
        fprintf(stderr, "connect error\n");
        return -1;
    }

    return sockfd;
}

tcp.h:

/*client/tcp.h*/

#ifndef TCP_H
#define TCP_H

/*
 * link IP:port using tcp
 * return sock file descriptor of the link (-1 if error)
 */
int link_server(char *IP, int port);

#endif // TCP_H
时间: 2024-12-29 06:51:19

jchat:linux聊天程序4:客户端的相关文章

jchat:linux聊天程序1:简介

做一个linux的聊天软件,虽然没什么创意,但是它可以用来锻炼和测试我对网络编程的掌握程度,也借此机会做一些有意思的程序. 这里做的是linux下一个命令行的客户端与服务器的聊天程序,没写界面,因为对qt不太熟,纯命令行朴素点,但是对于网络编程使用到就足够了. 这个程序实现了基本的用户注册登录功能,信息发送与接收功能,未读信息存入数据库并在用户登录时获取. 另外,使用了mysql作为存储的数据库,存储着用户注册的信息与用户之间发送的消息. 服务器负责接收客户端的一切请求,对于每个客户端进程都新建

jchat:linux聊天程序3:服务器

makefile: jchat_server: main.o process.o sql.o gcc -o jchat_server main.o process.o sql.o -L/usr/lib/mysql -lmysqlclient rm -f *.o *.gch *~ main.o: main.c process.h sql.h gcc -c main.c process.h sql.h -I/usr/include/mysql process.o: process.h process

jchat:linux聊天程序2:MySQL

该软件使用的数据库为MySQL,因为它免费.开源,在linux下几乎就是最好的选择. 首先要在mysql中root用户新建数据库并赋权给本用户: 1 create database jchat; 2 grant all on jchat.* to 'huanglianjing'; 然后登录mysql的huanglianjing用户添加数据表: 用户表: 1 create table user 2 ( 3 user varchar(20) not null, 4 passwd varchar(20

boost asio异步读写网络聊天程序客户端 实例详解

// // chat_client.cpp // ~~~~~~~~~~~~~~~ // // Copyright (c) 2003-2013 Christopher M. Kohlhoff (chris at kohlhoff dot com) // // Distributed under the Boost Software License, Version 1.0. (See accompanying // file LICENSE_1_0.txt or copy at http://ww

Socket聊天程序——Common

写在前面: 上一篇记录了Socket聊天程序的客户端设计,为了记录的完整性,这里还是将Socket聊天的最后一个模块--Common模块记录一下.Common的设计如下: 功能说明: Common模块主要是数据交互,这里使用JSON数据进行交互,common模块定义了各类交互信息,SendHelper实现的socket信息的传送,I18N是语言话,ConstantValue是系统中的配置以及常量(这里常量都是用接口,这个可能不太好),对于ReturnMessage拥有一系列的DTO作为其cont

Linux下C语言多线程,网络通信简单聊天程序

原文:Linux下C语言多线程,网络通信简单聊天程序 功能描述:程序应用多线程技术,可是实现1对N进行网络通信聊天.但至今没想出合适的退出机制,除了用Ctr+C.出于演示目的,这里采用UNIX域协议(文件系统套接字),程序分为客户端和服务端.应用select函数来实现异步的读写操作. 先说一下服务端:首先先创建套接字,然后绑定,接下进入一个无限循环,用accept函数,接受“连接”请求,然后调用创建线程函数,创造新的线程,进入下一个循环.这样每当有一个新的“连接”被接受都会创建一个新的线程,实现

Linux 下基于多线程服务器/客服端聊天程序源码

Linux 下基于多线程服务器/客服端聊天程序,采用阻塞的socket技术,和多线程技术实现. 客服端程序:client.c #include<stdio.h> #include<stdlib.h> #include<string.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <netinet/ip.h>

一个hello/hi的简单的网络聊天程序和python Socket API与Linux Socket API之间的关系

1.Socket概述 套接字(socket)是一个抽象层,应用程序可以通过它发送或接收数据,可对其进行像对文件一样的打开.读写和关闭等操作.套接字允许应用程序将I/O插入到网络中,并与网络中的其他应用程序进行通信.网络套接字是IP地址与端口的组合. 套接字可以看成是两个网络应用程序进行通信时,各自通信连接中的一个端点.通信时,其中的一个网络应用程序将要传输的一段信息写入它所在主机的Socket中,该Socket通过网络接口卡的传输介质将这段信息发送给另一台主机的Socket中,使这段信息能传送到

通过基于java实现的网络聊天程序分析java中网络API和Linux Socket API关系

1. 引言 socket网络编程,可以指定不同的通信协议,在这里,我们使用TCP协议实现基于java的C/S模式下“hello/hi”网络聊天程序 2. 目标 1). 通过该网络聊天程序,了解java Socket API接口的基本用法 2). java Socket API简要介绍 3). linux socket API 简单分析 4). tcp协议的连接和终止 5). 探究java socket API 和 linux socket api之间的关系 3. linux socket API