#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <strings.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#define serv_port 9000
#define buff_size 1024
struct user
{
int socketfd;
char name[20];
char toname[20];
int result; // 0 代表失敗 1代表成功 2 代表別人給你發(fā)的信息 3代表沒(méi)注冊(cè) 4錯(cuò)誤的指令
char msg[100];
int cmd; // 5 代表注冊(cè)用戶(hù) 10 // 代表發(fā)送信息
};
struct usermanage
{
int flag[20]; // 表明哪個(gè)空缺
struct user users[20];
};
pthread_mutex_t mutex;
struct usermanage umge;
void save_user(int socket_fd, struct user * userinfo)
{
pthread_mutex_lock(&mutex);
int i = 0;
for (i = 0; i < 20; i )
{
if (umge.flag[i] == 1)
{
continue;
}
umge.users[i].socketfd = socket_fd;
strcpy(umge.users[i].name, userinfo->name);
userinfo->result = 1;
umge.flag[i] = 1;
printf ("%s register success!n", umge.users[i].name);
break;
}
pthread_mutex_unlock(&mutex);
}
int server_request(int cfd)
{
int readsize, writesize;
int ret = 0;
int i;
struct user userinfo;
int toname_fd = -1;
int isregister = -1;
while (readsize = read(cfd, &userinfo, sizeof(userinfo)))
{
if (readsize == -1)
{
perror("read");
return -1;
}
if (userinfo.cmd == 5) // 注冊(cè)用戶(hù)
{
save_user(cfd, &userinfo); // 將用戶(hù)信息進(jìn)行保存
}
else if (userinfo.cmd == 10) // 發(fā)送信息
{
// 檢測(cè)該用戶(hù)是否注冊(cè)
for (i = 0; i < 20; i )
{
if (umge.flag[i] == 1)
{
if (umge.users[i].socketfd == cfd)
{
if (strcmp(umge.users[i].name, userinfo.name) == 0)
{
isregister = 1;
}
}
}
}
if(isregister == 1)
{
// 尋找要發(fā)送的用戶(hù)
for (i = 0; i < 20; i )
{
if (umge.flag[i] == 1)
{
// 找到了要發(fā)送的用戶(hù),將其socket保存起來(lái)
if (strcmp(umge.users[i].name, userinfo.toname) == 0)
{
toname_fd = umge.users[i].socketfd;
}
}
}
if(toname_fd != -1) // 沒(méi)找到要發(fā)送的用戶(hù)
{
userinfo.result = 2; // 找到用戶(hù)將其返回狀態(tài)標(biāo)為1
writesize = write(toname_fd, &userinfo, sizeof(userinfo));
if (writesize == -1)
{
perror("write");
return -1;
}
printf ("%s send msg to %s : %sn", userinfo.name, userinfo.toname, userinfo.msg);
userinfo.result = 1; // 發(fā)送成功
}
}
else
{
userinfo.result = 3; // 沒(méi)有注冊(cè)
}
}
else
{
userinfo.result = 4; // 錯(cuò)誤的指令
}
writesize = write(cfd, &userinfo, sizeof(userinfo));
if (writesize == -1)
{
perror("write");
return -1;
}
memset(userinfo.msg, 0, sizeof(userinfo.msg));
}
}
int main()
{
int listen_sockfd;
int ret;
struct sockaddr_in server_addr; // 服務(wù)器地址結(jié)構(gòu)
struct sockaddr_in client_addr; // 客戶(hù)端的地址
pthread_mutex_init(&mutex, null);
// 創(chuàng)建監(jiān)聽(tīng)套接字
listen_sockfd = socket(af_inet, sock_stream, 0);
if (listen_sockfd == -1)
{
perror("create socket error");
return -1;
}
// 初始化服務(wù)器地址結(jié)構(gòu)
bzero(&server_addr, sizeof(server_addr)); // 將地址結(jié)構(gòu)變量清零
server_addr.sin_family = af_inet; // 選擇ipv4地址
server_addr.sin_addr.s_addr = htonl(inaddr_any); // 監(jiān)聽(tīng)本地任意ip地址
server_addr.sin_port = htons(serv_port); // 將本地端口號(hào)轉(zhuǎn)化為網(wǎng)絡(luò)端口號(hào)
// 綁定本地地址和端口號(hào)
ret = bind(listen_sockfd, (struct sockaddr *)&server_addr, sizeof (server_addr));
if (ret == -1)
{
perror ("bind error");
return -1;
}
// 監(jiān)聽(tīng)套接字
ret = listen(listen_sockfd, 20);
if (ret == -1)
{
perror("listen error");
return -1;
}
while(1)
{
int clientfd;
socklen_t client_len = sizeof(client_addr);
clientfd = accept(listen_sockfd, (struct sockaddr *)&client_addr, &client_len);
if (clientfd == -1)
{
perror("accept error");
return -1;
}
pthread_t tid;
// 創(chuàng)建線(xiàn)程處理客戶(hù)端請(qǐng)求
int ret = pthread_create(&tid, null, server_request, (void *)clientfd);
if (ret != 0)
{
printf ("cre