服务器与客户端简单通信 ——server

来源:互联网 发布:php 图片上传插件 编辑:程序博客网 时间:2024/05/17 00:07
#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 代表别人给你发的信息 3代表没注册 4错误的指令
char msg[100];
int cmd;  // 5 代表注册用户  10 // 代表发送信息
};


struct userManage
{
int flag[20];   // 表明哪个空缺 
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)             // 注册用户
{
save_user(cfd, &userInfo);     // 将用户信息进行保存
}















else if (userInfo.cmd == 10)  // 发送信息
{
// 检测该用户是否注册
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)
{
// 寻找要发送的用户
for (i = 0; i < 20; i++)
{
if (uMge.flag[i] == 1)
{
// 找到了要发送的用户,将其socket保存起来
if (strcmp(uMge.users[i].name, userInfo.toName) == 0)
{
toname_fd = uMge.users[i].socketfd;
}
}
}
if(toname_fd != -1)  // 没找到要发送的用户
{
userInfo.result = 2;   // 找到用户将其返回状态标为1 
writeSize = write(toname_fd, &userInfo, sizeof(userInfo));
if (writeSize == -1)
{
perror("write");
return -1;
}

printf ("%s send msg to %s : %s\n", userInfo.name, userInfo.toName, userInfo.msg);
userInfo.result = 1;  // 发送成功
}
}
else
{
userInfo.result = 3;  // 没有注册
}
}
else
{
userInfo.result = 4;  // 错误的指令
}

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;  // 服务器地址结构
struct sockaddr_in client_addr;  // 客户端的地址

pthread_mutex_init(&mutex, NULL);

// 创建监听套接字
listen_sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (listen_sockfd == -1)
{
perror("create socket error");
return -1;
}

// 初始化服务器地址结构
bzero(&server_addr, sizeof(server_addr));          // 将地址结构变量清零
  server_addr.sin_family = AF_INET;                  // 选择IPV4地址
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);   // 监听本地任意IP地址
server_addr.sin_port = htons(SERV_PORT);           // 将本地端口号转化为网络端口号

// 绑定本地地址和端口号
ret = bind(listen_sockfd, (struct sockaddr *)&server_addr, sizeof (server_addr));
if (ret == -1)
{
perror ("bind error");
return -1;
}


// 监听套接字
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;
// 创建线程处理客户端请求
int ret = pthread_create(&tid, NULL, server_request, (void *)clientfd);
if (ret != 0)
{
printf ("create pthread error!\n");
return -1;
}
pthread_detach(tid); // 线程分离
}

pthread_mutex_destroy(&mutex);

return 0;
}