// 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和数据库的一些使用---郭雪彬
标签:
查看更多关于Socket和数据库的一些使用---郭雪彬的详细内容...
声明:本文来自网络,不代表【好得很程序员自学网】立场,转载请注明出处:http://www.haodehen.cn/did118706