网络聊天室(还有推出未完成)
/服务器/
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<sys/stat.h>
#include<string.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
#include<pthread.h>
#include<sys/wait.h>
#include<stdlib.h>
#define ERR_MSG(msg) do{\
perror(msg);\
printf("line: __%d__\n", __LINE__);\
}while(0)
//服务器IP端口信息
#define IP_SER "192.168.8.151"
#define PORT_SER 8080
int sfd;
//客户端信息链表
typedef struct node
{
struct sockaddr_in cin;
char name[20];
int len;
struct node* next;
}save_cin_info;
//创建存储客户端信息结构体
//方便线程使用创建全局变量
save_cin_info list_cin;
//消息包结构体协议
struct message
{
char type;
char name[20];
char text[128];
};
//线程回调函数声明
void* callback_RCV(void* arg);
void* callback_SND(void* arg);
int do_loin(struct message msg_rcv, struct sockaddr_in cin);
int do_chat(struct message msg_rcv, struct sockaddr_in cin);
/* condition */
int main(int argc, const char *argv[])
{
基本框架///
sfd = socket(AF_INET, SOCK_DGRAM, 0);
if (sfd < 0)
{
ERR_MSG("socket");
return -1;
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT_SER);
sin.sin_addr.s_addr = inet_addr(IP_SER);
if (bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0)
{
ERR_MSG("bind");
return -1;
}
printf("bind success __%d__\n", __LINE__);
基本框架///
//初始化存储客户端信息结构体
memset(&list_cin.cin, 0, sizeof(list_cin.cin));
//线程创建
pthread_t tid_rcv, tid_snd;
if (pthread_create(&tid_rcv, NULL, callback_RCV, NULL) != 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
if (pthread_create(&tid_snd, NULL, callback_SND, NULL) != 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
pthread_join(tid_rcv, NULL);
pthread_join(tid_snd, NULL);
close(sfd);
return 0;
}
void* callback_RCV(void* arg)
{
//接受协议
struct message msg_rcv;
memset(&msg_rcv, 0, sizeof(struct message));
//客户端信息
struct sockaddr_in cin;
socklen_t cin_len = sizeof(cin);
while (1)
{
memset(&msg_rcv, 0, sizeof(msg_rcv));
int res_rcv = 0;
res_rcv = recvfrom(sfd, &msg_rcv, sizeof(struct message), 0, (struct sockaddr*)&cin, &cin_len);
if (res_rcv < 0)
{
ERR_MSG("recvfrom");
return NULL;
}
printf("type = %c name = %s text = %s\n", msg_rcv.type, msg_rcv.name, msg_rcv.text);
switch(msg_rcv.type)
{
case 'L':
do_loin(msg_rcv, cin);
break;
case 'C':
do_chat(msg_rcv, cin);
break;
case 'Q':
//do_quit(msg_rcv);
break;
default:
continue;
break;
}
}
}
int do_loin(struct message msg_rcv, struct sockaddr_in cin)
{
//遍历客户端信息结构体发送登录信息
save_cin_info* temp1 = &list_cin;
while (temp1->next != NULL)
{
temp1 = temp1->next;
//发送给用户登录消息
int res = 0;
char buf_loin[64] = "";
sprintf(buf_loin, "[ %s ] 登录聊天室\n", msg_rcv.name);
res = sendto(sfd, buf_loin, sizeof(buf_loin), 0, (struct sockaddr*)&temp1->cin, (socklen_t)sizeof(temp1->cin));
if (res < 0)
{
ERR_MSG("sendto");
return -1;
}
printf("发出登录消息\n");
}
//创建节点添加到链表
//初始化
save_cin_info* new = (save_cin_info*)malloc(sizeof(save_cin_info));
if (NULL == new)
{
ERR_MSG("malloc");
return -1;
}
//将新客户端信息添加到新结构体中
new->cin = cin;
strcpy(new->name, msg_rcv.name); //将用户端ip信息和用户名绑定
new->next = NULL;
//插入(头插)
save_cin_info *temp2 = list_cin.next;
list_cin.next = new;
new->next = temp2;
list_cin.len++;
//遍历链表输出,检查所有用户名
temp2 = &list_cin;
while (temp2->next != NULL)
{
temp2 = temp2->next;
printf("name = %s\n", temp2->name);
}
return 0;
}
int do_chat(struct message msg_rcv, struct sockaddr_in cin)
{
int res = 0;
char buf_chat[256] = "";
//sprintf(buf_chat, "[ %s ] : %s\n", msg_rcv.name, msg_rcv.text);
//遍历链表通过cin找到对应客户端的用户名
char name[20] = "";
save_cin_info* temp = &list_cin;
printf("len = %d\n", list_cin.len);
for (int i=0; i<list_cin.len; i++)
{
temp = temp->next;
//获取cin对应的用户名
strcpy(name, temp->name);
printf("temp->name = %s\n", temp->name);
//要回复给所有客户端的内容
sprintf(buf_chat, "[ %s ] : %s\n", name, msg_rcv.text);
res = sendto(sfd, buf_chat, sizeof(buf_chat), 0, (struct sockaddr*)&temp->cin, (socklen_t)sizeof(temp->cin));
if (res < 0)
{
ERR_MSG("sendto");
return -1;
}
}
return 0;
}
void* callback_SND(void* arg)
{
char buf_chat[128] = "";
char buf_system[128] = "";
int res = 0;
scanf("%s", buf_system);
save_cin_info* temp = &list_cin;
for (int i=0; i<list_cin.len; i++)
{
temp = temp->next;
//要回复给所有客户端的内容
sprintf(buf_chat, "[ system ] : %s\n", buf_system);
res = sendto(sfd, buf_chat, sizeof(buf_chat), 0, (struct sockaddr*)&temp->cin, (socklen_t)sizeof(temp->cin));
if (res < 0)
{
ERR_MSG("sendto");
return NULL;
}
}
return 0;
}
客户端
#include<stdio.h>
#include<string.h>
#include<sys/types.h>
#include<sys/socket.h>
#include<unistd.h>
#include<sys/stat.h>
#include<string.h>
#include<netinet/in.h>
#include<netinet/ip.h>
#include<arpa/inet.h>
#include<pthread.h>
#include<sys/wait.h>
#include<stdlib.h>
#define ERR_MSG(msg) do{\
perror(msg);\
printf("line: __%d__\n", __LINE__);\
}while(0)
//服务器IP端口信息
#define IP_SER "192.168.8.151"
#define PORT_SER 8080
//本地客户端IP端口信息
#define IP_CLI "192.168.8.151"
#define PORT_CLI 8801
struct message
{
char type;
char name[20];
char text[128];
};
//客户端套接字
int cfd;
//服务器IP和端口号信息
void* callback_text(void* arg);
void* callback_quit(void* arg);
int main(int argc, const char *argv[])
{
//基本框架///
cfd = socket(AF_INET, SOCK_DGRAM, 0);
if (cfd < 0)
{
ERR_MSG("socket");
return -1;
}
struct sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(PORT_SER);
sin.sin_addr.s_addr = inet_addr(IP_SER);
//基本框架///
//发送登录信息结构体
struct message msg_loin;
memset(&msg_loin, 0, sizeof(struct message));
msg_loin.type = 'L';
printf("请输入用户名>>> \n");
scanf("%s", msg_loin.name);
int s_res = 0;
s_res = sendto(cfd, &msg_loin, sizeof(struct message), 0, (struct sockaddr*)&sin, sizeof(sin));
if (s_res < 0)
{
ERR_MSG("sendto");
return -1;
}
//char bb[32] = "";
//recvfrom(cfd, bb, sizeof(bb), 0, NULL, NULL);
//创建线程
pthread_t tid_text, tid_quit;
if (pthread_create(&tid_text, NULL, callback_text, &sin) != 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
if (pthread_create(&tid_quit, NULL, callback_quit, NULL) != 0)
{
fprintf(stderr, "pthread_create failed\n");
return -1;
}
pthread_join(tid_text, NULL);
pthread_join(tid_quit, NULL);
close(cfd);
return 0;
}
void* callback_text(void* arg)
{
struct sockaddr_in sin = *(struct sockaddr_in*)arg;
struct message msg_chat;
memset(&msg_chat, 0, sizeof(msg_chat));
msg_chat.type = 'C';
printf("请输入发送的信息\n");
char buf_chat[128] = "";
int res = 0;
while (strcmp(buf_chat, "quit"))
{
bzero(buf_chat, sizeof(buf_chat));
scanf("%s", buf_chat);
strcpy(msg_chat.text, buf_chat);
res = sendto(cfd, &msg_chat, sizeof(struct message), 0, (struct sockaddr*)&sin, (socklen_t)sizeof(sin));
if (res < 0)
{
ERR_MSG("sendto");
return NULL;
}
//printf("buf_chat = %s size = %ld\n", buf_chat, strlen(buf_chat));
}
}
void* callback_quit(void* arg)
{
char buf_rcv[128] = "";
while (1)
{
recvfrom(cfd, buf_rcv, sizeof(buf_rcv), 0, NULL, NULL);
printf("%s\n", buf_rcv);
}
}