class="markdown_views prism-kimbie-light">
Linux 嵌入式 C 实现简单的网络聊天室
版权声明:
https://blog.csdn.net/qq_39603089/article/details/85080521
简单功能如下
- 服务器端接收用户信息,处理后转发给其他用户,如有用户登录或退出,服务器通知所有人;
- 群聊:用户发送的信息所有人都可以接收,接收的信息前面显示发送者的昵称和发送时间;
- 私聊:可以选定用户发送信息,其他用户看不到,该用户也使用相同的方式回复私聊信息;
- 保存和查看聊天记录,仅可查看自己保存的聊天记录,保存和读取聊天记录时需要使用文件锁; 保存和查看聊天记录,聊天记录保存在“./msgsave_昵称”文件中(“昵称”为保存者自己的昵称);
- 服务器的出错信息打印输出到屏幕上,同时发送给系统(/var/log/messages)。
使用C/S 模式,参考下图:
源代码下载链接 与下方所示代码有所改进,添加与完善部分功能
https://blog.csdn.net/qq_39603089/article/details/85328262
先看客户端代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
GtkWidget *window;
GtkWidget *home;
int clientfd,b_file;
struct sockaddr_in clientaddr;
char user_name[50];
char fname[]="/var/tmp/";
void deal_pressed(GtkWidget *button, gpointer entry){
int sendbytes;
char *buff;
struct hostent *host;
char wel[]="Welcome";
host = gethostbyname("127.0.0.1");
buff = (char *)malloc(9);
const gchar *text = gtk_entry_get_text(GTK_ENTRY(entry));
if(strlen(text)==0){
printf("不能为空
");
}
else{
if ((clientfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
{
perror("fail to create socket");
exit(1);
}
bzero(&clientaddr, sizeof(clientaddr));
clientaddr.sin_family = AF_INET;
clientaddr.sin_port = htons((uint16_t)atoi("8787"));
clientaddr.sin_addr = *((struct in_addr *)host->h_addr);
if (connect(clientfd, (struct sockaddr *)&clientaddr, sizeof(struct sockaddr)) == -1)
{
perror("fail to connect");
exit(1);
}
if ((sendbytes = send(clientfd, text, strlen(text), 0)) == -1)
{
perror("fail to send");
exit(1);
}
if (recv(clientfd, buff, 7, 0) == -1)
{
perror("fail to recv");
exit(1);
}
if(strcmp(buff,wel)==0){
strcpy(user_name,text);
gtk_widget_destroy(window);
}else{
GtkWidget *dialog;
dialog = gtk_message_dialog_new((gpointer)window,
GTK_DIALOG_DESTROY_WITH_PARENT,
GTK_MESSAGE_ERROR,
GTK_BUTTONS_OK,
"昵称重复,拒绝登录");
gtk_window_set_title(GTK_WINDOW(dialog), "拒绝");
gtk_dialog_run(GTK_DIALOG(dialog));
gtk_widget_destroy(dialog);
close(clientfd);
}
}
}
void login(int argc,char *argv[]){
gtk_init(&argc, &argv);
window = gtk_window_new(GTK_WINDOW_TOPLEVEL);
gtk_window_set_title(GTK_WINDOW(window), "登录");
gtk_window_set_position(GTK_WINDOW(window), GTK_WIN_POS_CENTER);
gtk_widget_set_size_request(window, 300, 200);
gtk_window_set_resizable(GTK_WINDOW(window), FALSE);
g_signal_connect(window, "destroy", G_CALLBACK(gtk_main_quit), NULL);
GtkWidget *fixed = gtk_fixed_new();
gtk_container_add(GTK_CONTAINER (window), fixed);
GtkWidget *label_one = gtk_label_new("请输入昵称");
gtk_fixed_put(GTK_FIXED(fixed), label_one,120,30);
GtkWidget *entry = gtk_entry_new();
gtk_entry_set_max_length(GTK_ENTRY(entry),50);
gtk_editable_set_editable(GTK_EDITABLE(entry), TRUE);
gtk_fixed_put(GTK_FIXED(fixed), entry,70,60);
GtkWidget *button = gtk_button_new_with_label(" 登录 ");
gtk_fixed_put(GTK_FIXED(fixed), button,130,110);
g_signal_connect(button, "pressed", G_CALLBACK(deal_pressed), entry);
gtk_widget_show_all(window);
gtk_main();
}
GtkWidget *entryname;
void sendtouser(GtkButton *button, gpointer entry){
char *buf;
buf = (char *)malloc(1024);
memset(buf, 0, 1024);
int sendbytes;
const gchar *text = gtk_entry_get_text(GTK_ENTRY(entry));
const char *but = gtk_button_get_label(button);
if(strlen(text)==0){
printf("不能为空
");
}else{
if(strcmp(but,"--发送--")==0){
const gchar *name = gtk_entry_get_text(GTK_ENTRY(entryname));
if(strlen(name)==0){
printf("name为空。
");
return;
}
sprintf(buf,"%s%s%s%s
","User:",name,":",text);
if ((sendbytes = send(clientfd, buf, strlen(buf), 0)) == -1)
{
perror("fail to send");
}
return ;
}else{
sprintf(buf,"%s%s
","All::",text);
if ((sendbytes = send(clientfd, buf, strlen(buf), 0)) == -1)
{
perror("fail to send");
}
return ;
}
}
}
void savetxt(GtkButton *button, gpointer entry){
struct flock lock;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
lock.l_type = F_WRLCK;
lock.l_pid = -1;
int src_file, dest_file;
unsigned char buff[1024];
int real_read_len;
char txt_name[60];
sprintf(txt_name,"%s%s","./msgsave_",user_name);
src_file = open(fname, O_RDONLY);
dest_file = open(txt_name,O_WRONLY|O_CREAT, S_IRUSR|S_IWUSR|S_IRGRP|S_IROTH);
if (src_file< 0 || dest_file< 0)
{
return;
}
fcntl(dest_file, F_SETLKW, &lock);
while ((real_read_len = read(src_file, buff, sizeof(buff))) > 0)
{
write(dest_file, buff, real_read_len);
}
fcntl(dest_file, F_UNLCK, &lock);
close(dest_file);
close(src_file);
}
GtkTextBuffer *bufferuser;
GtkTextBuffer *buffernotice;
void *strdeal(void *arg){
char sign[10];
char buf[1024];
char s[1024];
struct flock lock;
lock.l_whence = SEEK_SET;
lock.l_start = 0;
lock.l_len = 0;
lock.l_type = F_WRLCK;
lock.l_pid = -2;
while(1){
memset(s, 0, strlen(s));
memset(sign, 0, strlen(sign));
memset(buf, 0, strlen(buf));
if(recv(clientfd, s, 1024, 0) <= 0)
{
perror("fail to recv");
close(clientfd);
exit(1);
}
int i=0;
int n=0;
int j=0;
for(i;i<strlen(s);i++){
if(n==1){
buf[j]=s[i];
j++;
}else{
if(s[i]==':'){
n++;
sign[j]='