天天看點

基于Linux的程序聊天室,簡單實作linux聊天室程式

花了很長時間用來練習掌握linux上socket的一個聊天室程式,可以實作的哦。

具體代碼如下

代碼一:

#ifndef _I_H

#define _I_H

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#include

#define SEVR_IP "127.0.0.1"

#define SEVR_PORT 8081

#define CNTNT_LEN 150

#define MSG_LEN sizeof(struct msg)

#define ADDR_LEN sizeof(struct sockaddr)

#define USR_LEN sizeof(struct user)

#define PRT_LEN 8

#define HSTR_LEN sizeof(struct chat_history)

int mainfd;

int sockfd;

int count;

struct sockaddr_in server;

struct msg

{

int flag;

int id_from;

int id_to;

char content[CNTNT_LEN];

char append[10];

};

struct user

{

int id;

char name[10];

char password[10];

char *p_chatlog;

struct sockaddr user_addr;

};

struct chat_history

{

char content[CNTNT_LEN];

char time[25];

int to;

int from;

int count;

};

extern int i_saveto_chat(struct msg *pmsg);

int i_clean_stdin ()

{

while ('\n' == getchar())

{

continue;

}

return(0);

}

int i_print(char *pmsg, int size)

{

int i = 1;

for (i; i<= size; i++)

{

if (*pmsg != '\n')

{

printf("%c", *pmsg);

pmsg ++;

}

else

{

return(0);

}

}

return(0);

}

int i_input(char *p_input)

{

char c = '\0';

int i;

for (i = 0; i < CNTNT_LEN; i++)

{

p_input[i] = getchar();

if (p_input[i] =='\n')

{

return(0);

}

}

printf("you have input long enough!\n");

return(0);

}

int i_socket(int domain, int type, int protocol)

{

int fd;

if ((fd = socket(domain, type, protocol)) == -1)

{

perror("creat socket error:");

exit(1);

}

return(fd);

}

int i_bind(int fd, const struct sockaddr *addr, int namelen)

{

if (-1 == bind(fd, addr, namelen))

{

perror("i_bind error:");

exit(1);

}

return (0);

}

int i_recvfrom(int fd, void *buf, size_t len, int flags,

struct sockaddr *addr, int *size)

{

if (-1 == recvfrom(fd, buf, len, flags, addr, size))

{

perror("i_recvfrom error:");

exit(1);

}

return(0);

}

int i_sendto(int fd, void *buf, size_t len, int flags,

struct sockaddr *addr, int size)

{

if (-1 == sendto(fd, buf, len, flags, addr, size))

{

perror("i_sendto error");

exit(1);

}

return (0);

}

int i_open(const char *pathname, int flags)

{

int fd;

if ((fd = open(pathname, flags)) == -1)

{

perror("open_failed");

exit(1);

}

return (fd);

}

int i_read(int fd, void *msg, int len)

{

if(-1 == read(fd, msg, len))

{

perror("i_read error");

exit(1);

}

return(0);

}

int i_write(int fd, void *msg, int len)

{

if (-1 == write(fd, msg, len))

{

perror("i_write error");

exit(0);

}

return(0);

}

int i_init()

{

mainfd = i_open("./chat_log", O_RDWR|O_CREAT);

sockfd = i_socket(AF_INET, SOCK_DGRAM, 0);

bzero(&server, sizeof(server));

server.sin_family = AF_INET;

inet_pton(AF_INET, "127.0.0.1", &server.sin_addr);

server.sin_port = htons(SEVR_PORT);

perror("init");

return (0);

}

char *i_get_time()

{

time_t time_now;

time(&time_now);

return(ctime(&time_now));

}

int i_lseek(int fd, off_t size, int position)

{

if (-1 == lseek(fd, size, position))

{

perror("seek error");

exit(1);

}

return(0);

}

int i_saveto_chat(struct msg *pmsg)

{

struct chat_history hstr;

bzero(&hstr, HSTR_LEN);

count = count + 1;

hstr.count =count;

hstr.from = pmsg->id_from;

hstr.to = pmsg->id_to;

strncpy(hstr.content, pmsg->content, CNTNT_LEN);

strncpy(hstr.time, i_get_time(), 25);

i_lseek(mainfd, 0, SEEK_END);

i_write(mainfd, &hstr, HSTR_LEN);

return(0);

}

int i_print_history(int len, int i)

{

struct chat_history chat_reader;

int j;

int position;

bzero(&chat_reader, HSTR_LEN);

if (i != 0)

{

position = len*i*HSTR_LEN;

i_lseek(mainfd, position, SEEK_END);

}

else

{

position = len*i*HSTR_LEN;

i_lseek(mainfd, HSTR_LEN, SEEK_SET);

}

for (j = 1; j <= len; j++)

{

i_read(mainfd, &chat_reader, HSTR_LEN);

printf("\n#item%d:id%dto id%d \n", j,

chat_reader.from, chat_reader.to);

i_print(chat_reader.content, CNTNT_LEN);

printf("\n Time:%s\n", chat_reader.time);

}

return(0);

}

#endif

代碼二:

#include "i.h"

int user_list_fd;

int init()

{

i_init();

user_list_fd = i_open("./user_list", O_RDWR|O_CREAT);

struct user usr;

memset((struct user*)&usr, '\0', sizeof(struct user));

i_lseek(user_list_fd, 0, SEEK_SET);

i_write(user_list_fd, (char*)&usr, USR_LEN);

i_bind(sockfd, (struct sockaddr*)&server, ADDR_LEN);

struct chat_history apple;

bzero(&apple, HSTR_LEN);

i_lseek(mainfd, 0, SEEK_SET);

i_write(mainfd, &apple, HSTR_LEN);

i_lseek(mainfd, -HSTR_LEN, SEEK_END);

i_read(mainfd, &apple, HSTR_LEN);

count = apple.count;

return(0);

}

int send_msg(struct msg *msg_recv, struct sockaddr *addr)

{

int i;

struct user usr;

printf("a ordinar message come !\n");

i = msg_recv->id_to;

i_lseek(user_list_fd, i*USR_LEN, SEEK_SET);

i_read(user_list_fd, &usr, USR_LEN);

strncpy(msg_recv->append, usr.name, 10);

i_sendto(sockfd, msg_recv, MSG_LEN, 0,

&(usr.user_addr), ADDR_LEN);

printf("id%d send a message to id%d sucess!\n", msg_recv->id_from, msg_recv->id_to);

return(0);

}

int check_login(struct msg *msg_recv, struct sockaddr *addr)

{

int i = msg_recv->id_from;;

struct user usr;

printf("a login request come!\n");

i_lseek(user_list_fd, i*USR_LEN, SEEK_SET);

i_read(user_list_fd, &usr, USR_LEN);

int n;

n = strcmp(usr.password, msg_recv->content);

if (n == 0)

{

i_lseek(user_list_fd, -USR_LEN, SEEK_CUR);

usr.user_addr = *addr;

i_write(user_list_fd, &usr, USR_LEN);

i_sendto(sockfd, (struct msg*)msg_recv, sizeof(struct msg), 0,

&(usr.user_addr), ADDR_LEN);

}

else

{

if (0 != n)

{

printf("id %d login error.\n", i);

bzero(msg_recv->content, CNTNT_LEN);

msg_recv->flag = -1;

i_sendto(sockfd, (struct msg*)msg_recv, sizeof(struct msg), 0,

&(usr.user_addr), ADDR_LEN);

}

return(1);

}

printf("Id %d login sucess!\n", i);

return(0);

}

int reg_user(struct msg *msg_recv, struct sockaddr *addr)

{

struct user usr;

printf("a regit requet come:\n");

int n;

i_lseek(user_list_fd, -USR_LEN, SEEK_END);

i_read(user_list_fd, &usr, USR_LEN);

const char *name;

const char *password;

name = &(msg_recv->content[0]);

password = &(msg_recv->content[10]);

strcpy((usr.name), name);

strcpy(usr.password, password);

memcpy(&(usr.user_addr),addr, ADDR_LEN);

usr.id = (usr.id + 1);

i_lseek(user_list_fd, 0, SEEK_END);

i_write(user_list_fd, &usr, USR_LEN);

msg_recv->id_from = usr.id;

i_sendto(sockfd, (struct msg*)msg_recv, sizeof(struct msg), 0,

addr, ADDR_LEN);

printf("Id %d regist sucess!\n", usr.id);

return(0);

}

int msg_cntl()

{

struct msg msg_recv;

struct sockaddr addr_recv;

printf("begin listen input...\n");

int size = ADDR_LEN;

for (;;)

{

bzero(&msg_recv, MSG_LEN);

i_recvfrom(sockfd, &msg_recv, sizeof(struct msg), 0,

&addr_recv, &size);

printf("message received...\n");

i_saveto_chat(&msg_recv);

switch (msg_recv.flag)

{

case 1 :

send_msg(&msg_recv,(struct sockaddr*)&addr_recv);

break;

case 2 :

check_login(&msg_recv, (struct sockaddr*)&addr_recv);

break;

case 3 :

reg_user(&msg_recv, (struct sockaddr*)&addr_recv);

break;

default :

break;

}

}

return(0);

}

int exit_sys()

{

close(sockfd);

close(mainfd);

close(user_list_fd);

printf("exit system");

kill(0, SIGABRT);

exit(0);

}

int get_page_size()

{

struct chat_history page_size_reader;

i_lseek(mainfd, -HSTR_LEN, SEEK_END);

i_read(mainfd, &page_size_reader, HSTR_LEN);

return(page_size_reader.count);

}

int read_chat_history()

{

printf("****char*history***");

printf("(n-nextpage; p-prepage; q-quit)\n");

int page_num;

int remains;

int berry = get_page_size();

page_num = berry / 8;

remains = berry % 8;

if (remains != 0)

page_num ++;

else

page_num = page_num;

printf("there are %d page total %d items",

page_num, berry);

int i = -1;

while (1)

{

char flag;

if ((berry + i*8) >= 0)

{

printf("(%d~%d)\n", (berry + i*8), (berry + (i+1)*8));

i_print_history(PRT_LEN, i);

printf("@@@\n");

while ('\n' == (flag = getchar()))

{

}

switch (flag)

{

case 'p' :

i--;

break;

case 'n' :

i++;

break;

case 'q' :

return(0);

default :

break;

}

if (i >= 0)

{

printf("have at the end!\n");

printf("return to menu!\n");

}

}

else

{

printf("(1~%d)\n", remains);

i_print_history(remains, 0);

printf("#########over##############\n");

return(0);

}

}

return(0);

}

int menu()

{

sleep(1);

printf("----------help----menu---------\n");

printf("\t r--report to user\n");

printf("\t c--chat history\n");

printf("\t h--help menu\n");

printf("\t e--exit the system\n");

printf("----------help_menu---------\n");

int command = 0;

printf("input command>");

command = getchar();

switch(command)

{

case 'c':

read_chat_history();

break;

case 'e':

exit_sys();

break;

case 'r':

//report();

//break;

default :

menu();

break;

}

getchar();

return(0);

}

int main()

{

init();

pid_t pid;

switch (pid = fork())

{

case -1 :

perror("fork error\n");

exit(1);

break;

case 0 :

msg_cntl();

break;

default :

menu();

break;

}

return(0);

}

代碼三:

#include "i.h"

#define START_PORT 8089

struct sockaddr_in my_addr;

int my_id;

int my_log();

int i_send_msg()

{

int id;

struct msg the_msg;

char end = '@';

printf("input recver id:");

scanf("%d", &id);

getchar();

printf("\ninput content:");

i_input(the_msg.content);

char flag = 'y';

if (1)

{

the_msg.flag = 1;

the_msg.id_from = my_id;

the_msg.id_to = id;

i_sendto(sockfd, &the_msg, sizeof(struct msg), 0,

(struct sockaddr*)&server, sizeof(struct sockaddr));

i_saveto_chat(&the_msg);

printf("send to id:%d success.\n", my_id);

return(0);

}

else

return(1);

return(0);

}

int reply()

{

return(0);

}

int send_file()

{

return(0);

}

int init()

{

struct ifreq req;

struct sockaddr_in *host;

int port;

i_init();

bzero(&my_addr, sizeof(struct sockaddr));

my_addr.sin_family = AF_INET;

strcpy(req.ifr_name, "lo");

if ( ioctl(sockfd, SIOCGIFADDR, &req) < 0 )

{

perror("get local ip error");

exit(1);

}

host = (struct sockaddr_in*)&(req.ifr_addr);

printf("ip: %s\n", inet_ntoa(host->sin_addr));

memcpy(&my_addr, (struct sockaddr_in*)&(req.ifr_addr),

sizeof(struct sockaddr_in));

port = START_PORT;

do

{

port++;

my_addr.sin_port = htons(port);

bind(sockfd, (struct sockaddr*)&my_addr,

sizeof(struct sockaddr));

}

while (errno == EADDRINUSE);

struct chat_history apple;

memset(&apple, 'b', HSTR_LEN);

i_lseek(mainfd, 0, SEEK_SET);

apple.count = 0;

i_write(mainfd, &apple, HSTR_LEN);

i_lseek(mainfd, -HSTR_LEN, SEEK_END);

i_read(mainfd, &apple, HSTR_LEN);

count = apple.count;

printf("port:%d\n", port);

printf("init successful!!!\n");

return(0);

}

int get_page_size()

{

struct chat_history page_size_reader;

i_lseek(mainfd, -HSTR_LEN, SEEK_END);

i_read(mainfd, &page_size_reader, HSTR_LEN);

return(page_size_reader.count);

}

int read_chat_history()

{

printf("****char*history***");

printf("(n-nextpage; p-prepage; q-quit)\n");

int page_num;

int remains;

int berry = get_page_size();

page_num = berry / 8;

remains = berry % 8;

if (remains != 0)

page_num ++;

else

page_num = page_num;

printf("there are %d page total %d items",

page_num, berry);

int i = -1;

while (1)

{

char flag;

if ((berry + i*8) >= 0)

{

printf("(%d~%d)\n", (berry + i*8), (berry + (i+1)*8));

i_print_history(PRT_LEN, i);

printf("@@@\n");

while ('\n' == (flag = getchar()))

{

}

switch (flag)

{

case 'p' :

i--;

break;

case 'n' :

i++;

break;

case 'q' :

return(0);

default :

break;

}

if (i >= 0)

{

printf("have at the end!\n");

printf("return to menu!\n");

}

}

else

{

printf("(1~%d)\n", remains);

i_print_history(remains, 0);

printf("#########over##############\n");

return(0);

}

}

return(0);

}

void exit_sys()

{

close(sockfd);

close(mainfd);

kill(0, SIGABRT);

exit(0);

}

int print_menu()

{

printf("\n--------------help--menu----------------\n");

printf("\t h--help munu\n");

printf("\t s--send message\n");

printf("\t r--reply to\n");

printf("\t c--chat history\n");

printf("\t f--send files\n");

printf("\t e--exit the system\n");

printf("----------------help--menu----------------\n");

}

int get_input(char *command)

{

printf(">");

scanf("%c", command);

return(1);

}

int menu()

{

sleep(1);

print_menu();

char command;

while (1 == get_input(&command))

{

switch(command)

{

case 'h':

print_menu();

break;

case 's':

i_send_msg();

break;

case 'r':

reply();

break;

case 'f':

send_file();

break;

case 'c':

read_chat_history();

break;

case 'e':

exit_sys();

break;

default :

printf(">");

break;

}

}

return(0);

}

int ordnary_msg_recv(struct msg *pmsg)

{

char time_info[25];

char end_symble;

end_symble = '&';

printf("Message:from %s(id%d) to U:\n", pmsg->append, pmsg->id_from);

i_print(pmsg->content, MSG_LEN);

printf("\n\t%s", i_get_time());

return(0);

}

int file_msg_recv(struct msg *pmsg)

{

}

int handle_msg(struct msg *pmsg)

{

if (pmsg->flag == 1)

{

ordnary_msg_recv(pmsg);

return(0);

}

else if (pmsg->flag >= 4)

{

file_msg_recv(pmsg);

return(0);

}

return(0);

}

int listen_msg()

{

struct msg msg_recv;

struct sockaddr addr_recv;

int len = ADDR_LEN;

printf("begin listen...\n");

for ( ; ; )

{

i_recvfrom(sockfd, &msg_recv, MSG_LEN, 0,

&addr_recv, &len);

i_saveto_chat(&msg_recv);

ordnary_msg_recv(&msg_recv);

}

}

int login()

{

printf("*****login>>\n");

printf("id:");

scanf("%d", &my_id);

char password[15];

printf("\npassword(*less 15 char):");

scanf("%s", password);

getchar();

struct msg log_msg;

bzero(&log_msg, MSG_LEN);

log_msg.flag = 2;

log_msg.id_from = my_id;

log_msg.id_to = 0;

strncpy(log_msg.content, password, 15);

i_saveto_chat(&log_msg);

i_sendto(sockfd, (struct msg*)&log_msg, MSG_LEN, 0,

(struct sockaddr*)&server, sizeof(struct sockaddr));

//printf("log_msg : %d\n", log_msg.id_from);

//printf("password: %s\n", log_msg.content);

struct sockaddr in_addr;

int len = ADDR_LEN;

i_recvfrom(sockfd, (struct msg*)&log_msg, MSG_LEN,0,

&in_addr, &len);

if (2 == log_msg.flag)

{

printf("login success\n");

return(0);

}

else

{

printf("login error:%s\n", log_msg.content);

printf("please relog..\n");

menu();

}

return (0);

}

int regist()

{

printf("*****regist>>\n");

char name[10];

bzero(name, 10);

printf("input your chat name(less 8 char):");

scanf("%s", name);

//name[9] = ';';

char password[15];

bzero(password, 15);

printf("\ninput your password(less 14 char):");

scanf("%s", password);

struct msg reg_msg;

bzero(&reg_msg, MSG_LEN);

reg_msg.flag = 3;

reg_msg.id_from = 0;

reg_msg.id_to = 0;

bzero(reg_msg.content, CNTNT_LEN);

strncpy(reg_msg.content, name, 10);

strncpy(&(reg_msg.content[10]), password, 15);

reg_msg.content[25] = '\n';

i_saveto_chat(&reg_msg);

i_sendto(sockfd, (struct msg*)&reg_msg, sizeof(struct msg), 0,

(struct sockaddr*)&server, ADDR_LEN);

printf("wating for server reply...\n");

struct sockaddr in_addr;

struct msg msg_back;

int len = ADDR_LEN;

bzero(&in_addr, ADDR_LEN);

bzero(&msg_back, MSG_LEN);

i_recvfrom(sockfd,(struct msg*)&msg_back, MSG_LEN,0,

&in_addr, &len);

if (3 != msg_back.flag)

{

printf("error: %s \n", msg_back.content);

exit(1);

}

else

my_id = msg_back.id_to;

printf("congratulate! you have regist"

"id %s(id %d) success\n", msg_back.content, msg_back.id_to);

login();

return(0);

}

int my_log()

{

char flag;

printf("are you want login or regist(l/r)\n");

scanf("%c", &flag);

getchar();

switch (flag){

case 'l' :

login();

break;

case 'r' :

regist();

break;

default :

printf("error input\n");

my_log();

break;

}

return (0);

}

int main()

{

init();

printf("\n************welcome!************\n");

my_log();

pid_t pid;

switch (pid = fork())

{

case -1 :

perror("fork error!\n");

exit(1);

break;

case 0 :

listen_msg();

break;

default :

menu();

break;

}

}

希望本文所述對大家實作linux多人聊天室程式。