Socket和数据库的一些使用---郭雪彬
最近偶尔有时间,研究了下Socket的使用,虽然不简单,不过还是挺有意思,刚好咱们带头大哥需要我们发檄文,也罢,那就来一篇,废话不多说,直接入正题
struct sockaddr_in server_addr;
pthread_mutex_t mut;
struct kevent events[10];
//IP地址、端口和协议族
server_addr.sin_len = sizeof(struct sockaddr_in);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr(ipAddress);
bzero(&(server_addr.sin_zero),8);
//创建socket
int server_sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (server_sock_fd == -1) {
perror("socket error");
return NULL;
}
int on=1;
if((setsockopt(server_sock_fd,SOL_SOCKET,SO_REUSEADDR,&on,sizeof(on)))<0)
{
perror("setsockopt failed");
exit(EXIT_FAILURE);
}
//绑定socket
int bind_result = bind(server_sock_fd, (struct sockaddr *)&server_addr, sizeof(server_addr));
if (bind_result == -1) {
perror("bind error");
return NULL;
} //监听
if (listen(server_sock_fd, BACKLOG) == -1) {
perror("listen error");
return NULL;
}
struct timespec timeout = {10,0};
//kqueue
int kq = kqueue();
if (kq == -1) {
perror("创建kqueue出错!\n");
exit(1);
}
struct kevent event_change;
EV_SET(&event_change, STDIN_FILENO, EVFILT_READ, EV_ADD, 0, 0, NULL);
kevent(kq, &event_change, 1, NULL, 0, NULL);
EV_SET(&event_change, server_sock_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
kevent(kq, &event_change, 1, NULL, 0, NULL); while (1) { int ret = kevent(kq, NULL, 0, events, 10, &timeout);
if (ret < 0) {
printf("kevent 出错!\n");
continue;
}else if(ret == 0){
printf("kenvent 超时!\n");
continue;
}else{
//ret > 0 返回事件放在events中
for (int i = 0; i < ret; i++) {
struct kevent current_event = events[i];
//kevent中的ident就是文件描述符
if (current_event.ident == STDIN_FILENO) {
//标准输入
bzero(input_msg, BUFFER_SIZE);
fgets(input_msg, BUFFER_SIZE, stdin);
//输入 ".quit" 则退出服务器
if (strcmp(input_msg, QUIT_CMD) == 0) {
exit(0);
}
for (int i=0; i<CONCURRENT_MAX; i++) {
if (client_fds[i]!=0) {
send(client_fds[i], input_msg, BUFFER_SIZE, 0);
}
}
}else if(current_event.ident == server_sock_fd){
//有新的连接请求
struct sockaddr_in client_address;
socklen_t address_len;
int client_socket_fd = accept(server_sock_fd, (struct sockaddr *)&client_address, &address_len);
if (client_socket_fd > 0) {
int index = -1;
for (int i = 0; i < CONCURRENT_MAX; i++) {
if (client_fds[i] == 0) {
index = i;
client_fds[i] = client_socket_fd;
break;
}
}
if (index >= 0) {
EV_SET(&event_change, client_socket_fd, EVFILT_READ, EV_ADD, 0, 0, NULL);
kevent(kq, &event_change, 1, NULL, 0, NULL);
printf("新客户端(fd = %d)加入成功 %s:%d \n",client_socket_fd,inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port));
/*客户端赋值*/
strcpy(client.ipAddress, inet_ntoa(client_address.sin_addr));
client.client_port = ntohs(client_address.sin_port);
client.client_ID = client_socket_fd; /*收集客户端信息并且存储到列表中*/
// if (AddClient(client, &clientList) == false) {
// fprintf(stderr, "Problem allcating memory\n");
// break;
// }
// if(ListIsFull(&clientList))
// {
// puts("The list is now full.\n");
// break;
// }
// if(ListIsEmpty(&clientList))
// {
// printf("NO client Connection");
// }else
// {
// Traverse(&clientList, showClients);
// }
// printf("在线客户端人数:%d\n", ListClientCount(&clientList)); if(!QueueIsFull(&line))
{
client.client_ID = client_socket_fd;
client.client_port = ntohs(client_address.sin_port);
strcpy(client.ipAddress, inet_ntoa(client_address.sin_addr));
EnQueue(client, &line); //将客户端添加到队列中
char msg[250];
char wellcome[250]; sprintf(msg,"新客户端(fd = %d) 加入成功 %s:%d",client_socket_fd,inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port)); sprintf(wellcome, "WellComm To NB Socket Server System your fd is %d addr is %s and port is %d",client_socket_fd,inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port)); //给所有客户端发送消息,除了刚刚连接上的客户端之外
for(int i=0; i<QueueItemCount(&line); i++)
{ if(index != i)
{
send(client_fds[i], msg, BUFFER_SIZE, 0);
}else
{
send(client_fds[i], wellcome, BUFFER_SIZE, 0);
}
}
} }else{ bzero(input_msg, BUFFER_SIZE);
strcpy(input_msg, "服务器加入的客户端数达到最大值,无法加入!\n");
send(client_socket_fd, input_msg, BUFFER_SIZE, 0);
printf("客户端连接数达到最大值,新客户端加入失败 %s:%d \n",inet_ntoa(client_address.sin_addr),ntohs(client_address.sin_port)); }
}
}else{
//处理某个客户端过来的消息
bzero(recv_msg, BUFFER_SIZE);
long byte_num = recv((int)current_event.ident,recv_msg,BUFFER_SIZE,0);
if (byte_num > 0) {
if (byte_num > BUFFER_SIZE) {
byte_num = BUFFER_SIZE;
}
recv_msg[byte_num] = '\0';
printf("客户端(fd = %d):%s\n",(int)current_event.ident,recv_msg); char delims[] = " ";
char *result = NULL; result = strtok(recv_msg, delims);
int k = 0;
while( result != NULL ) {
if(k==0)
{
strcpy(tableName, result); }else if (k == 1)
{
strcpy(userID, result); } k++;
printf( "result is \"%s\n", result );
result = strtok( NULL, delims );
}
sendMessage(client_fds[0], tableName, userID, user, &line);
break;
}else if(byte_num < 0){
printf("从客户端(fd = %d)接受消息出错.\n",(int)current_event.ident);
}else{
EV_SET(&event_change, current_event.ident, EVFILT_READ, EV_DELETE, 0, 0, NULL);
kevent(kq, &event_change, 1, NULL, 0, NULL);
close((int)current_event.ident);
for (int i = 0; i < CONCURRENT_MAX; i++) {
if (client_fds[i] == (int)current_event.ident) { Client *exitClient = (Client *)malloc(sizeof(Client)); exitClient->client_ID = (int)current_event.ident; // selectClientWithFds((int)current_event.ident, &line);
// int count = selectAllCilent(&line);//查找所有在线客户端 // bool del = deleteClientFormList(&clientList, *exitClient); // printf("%d\n",del); // Traverse(&clientList, showClients); // if(!ListIsEmpty(&clientList))
// {
// printf("\n排序后的元素\n");
// int desc = DescClientFromList(&clientList);
// Traverse(&clientList, showClients);
// printf("\n逆置后的元素\n");
// Reverse(&clientList);
// Traverse(&clientList, showClients);
// } // printf("在线客户端人数:%d\n", ListClientCount(&clientList)); printf("客户端(fd = %d)退出了\n",(int)current_event.ident);
// printf("剩余在线客户端个数%d\n",count);
client_fds[i] = 0;
break;
}
}
}
}
}
} } return NULL; }
void showClients(Client client)
{
// printf("客户端 IP: %s, port is %d, fds is %d\n",client.ipAddress, client.port, client.fds);
}
//void sendClientStates(int clientCount,Queue *pq)
//{
//
//
//} //对接收到的服务端消息进行处理,并且进行回应
void * sendMessage(int client_fds, char * message, char *userID, struct userTableInfo *userInfo, Queue *pq)
{
struct userMessage user = selectUserInfoWithUserID(message, userID);
printf("username is %s\n", user.name); send(client_fds, user.name, BUFFER_SIZE, 0);
send(client_fds, user.user_id, BUFFER_SIZE, 0);
send(client_fds, user.birthday, BUFFER_SIZE, 0); // pthread_mutex_unlock(&mut);
return NULL; }
以上是服务端部分代码,服务端将上线的客户端加入到链表中进行管理,当客户端上线时,服务端根据Socket的消息将客户端有关信息加入到链表中。


由于所有操作都在同一台计算机中,所以IP地址都是相同的
下面通过客户端对服务端发送相关指令获取对应的用户信息,该操作是基于客户端的指令,然后服务端通过相应指令对数据库进行查询,由于时间问题,目前该项目还不是很完善。

由于代码都是基于C语言,可以在linux, mac, windows等环境运行。
待续。。。。
Socket和数据库的一些使用---郭雪彬的更多相关文章
- MySql+Socket 完成数据库的增查Demo
需求: 利用MySql数据库结合前端技术完成用户的注册(要求不使用Web服务技术),所以 Demo采用Socket技术实现Web通信. 第一部分:数据库创建 数据库采用mysql 5.7.18, 数据 ...
- vue.js+socket.io+express+mongodb打造在线聊天
vue.js+socket.io+express+mongodb打造在线聊天 在线地址观看 http://www.chenleiming.com github地址 https://github.com ...
- vue.js+socket.io+express+mongodb打造在线聊天[二]
vue.js+socket.io+express+mongodb打造在线聊天[二] 在线地址观看 http://www.chenleiming.com github地址 https://github. ...
- 关于数据库管理系统DBMS--关系型数据库(MySQL/MariaDB)
数据库的结构(3种):层次,网状,关系型(用的最多): DBMS的三层模型: 视图层:面向最终用户: 逻辑层:面向程序员或DBA: 物理层:面向系统管理员: 关系型数据库管理系统——RDBMS: 主要 ...
- 实现对MySQL数据库进行分库/分表备份(shell脚本)
工作中,往往数据库备份是件非常重要的事情,毕竟数据就是金钱,就是生命!废话不多,下面介绍一下:如何实现对MySQL数据库进行分库备份(shell脚本) Mysq数据库dump备份/还原语法: mysq ...
- mysql数据库:mysql初识
1.什么是数据库 ***** 存放数据的仓库 已学习的文件操作的缺陷 1.IO操作 效率问题 2.多用户竞争数据 3.网络访问 ...
- 四种方案:将OpenStack私有云部署到Hadoop MapReduce环境中
摘要:OpenStack与Hadoop被誉为继Linux之后最有可能获得巨大成功的开源项目.这二者如何结合成为更猛的新方案?业内给出两种答案:Hadoop跑在OpenStack上或OpenStack部 ...
- 大V云集!参加首届阿里巴巴在线技术峰会的八大理由
由阿里巴巴集团.阿里巴巴技术协会(ATA)和阿里云云栖社区联合举办的首届阿里巴巴在线技术峰会(Alibaba Online Technology Summit)将于7月19日-21日20:00-21: ...
- java服务器端编程
由于要做手机端安卓程序,所以使用java来开发.后来又看了javaweb,觉得java还是很不错的,功能很强大,可以做很多事,最重要的是资源非常丰富,有很多开源的库框架之类. 最近用java做一个服务 ...
随机推荐
- C#中ref关键字的用法总结
ref表示引用的意思,C#中它有多种用法,这里简单总结一下: 1.按引用传递参数 具体可见:C#中的值传递与引用传递(in.out.ref) 2.引用局部变量 引用局部变量指的是在变量声明时使用ref ...
- Storm集群开启HA高可用
Storm开启HA高可用,包括Nimbus和UI开启两个及以上的进程. 基于已经安装好的Storm集群,开启关键节点角色的HA高可用. Storm安装请参考Storm集群安装Version1.0.1 ...
- zabbix5.0监控安全配置全过程
第一部分,安装 此安装配置为yum方式安装zabbix5.0 系统版本:CentOS Linux release 7.5.1804 (Core) zabbix版本:rpm -qa | grep zab ...
- 基于node和npm的命令行工具——tive-cli
前端开发过程中经常会用到各种各样的脚手架工具.npm全局工具包等命令行工具,如:Vue脚手架@vue/cli.React脚手架create-react-app.node进程守卫工具pm2.本地静态服务 ...
- kubeadm 安装Kubernetes 1.16.3 (CentOS7+IPVS+Calico)
目录 · . 一.更新系统内核(全部节点) · . 二.基础环境设置(全部节点) · . 1.修改 Host · . 2.修改 Hostname · . 3.主机时间同步 · . 4.关闭 ...
- linux VI命令快捷键
ctrl+f 下一页 ctrl+b 上一页 ctrl+u 上半页 ctrl+d 下半页 数字+空格键 根据当前光标移动多少个字母 0键 光标移动到第一个字母,是当前行的 $键 光标移动到最后一个字母 ...
- java mapreduce二次排序
原文链接: https://www.toutiao.com/i6765808056191156748/ 目的: 二次排序就是有下面的数据 a 3 a 1 a 100 c 1 b 2 如果只按照abc排 ...
- LINUX学习--nginx服务器的安装
一.安装环境 操作系统CentOS6.8 关闭SeLinux和iptables防火墙 二.网络yum源 将下面的软件下载到 /etc/yum.repos.d/ 的目录下 官方基础:http:// ...
- css处理工具PostCss
在 Web 应用开发中,CSS 代码的编写是重要的一部分.CSS 规范从最初的 CSS1 到现在的 CSS3,再到 CSS 规范的下一步版本,规范本身一直在不断的发展演化之中.这给开发人员带来了效率上 ...
- [WPF] 用 Effect 实现线条光影效果
1. 前言 几个月前 ChokCoco 大佬发布了一篇文章: CSS 奇技淫巧 | 妙用 drop-shadow 实现线条光影效果 在文章里实现了一个发光的心形线条互相追逐的效果: 现在正好有空就试试 ...