提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
服务器升级版,获取linux qt客户端传来的信息,并拆包和分别打印出来账号密码。并发包给客户端
#include <stdlib.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <stdio.h>
#include <signal.h>
typedef struct head { int fun; //定义数据包头 int dataLength; //描述数据长度 }HEAD_T; typedef struct user //定义用户数据包体 { char UserName[32]; char PassWord[32]; }USER_T;
typedef struct ret //定义服务器应答包体 { int flag; //定义用户登录返回状态 char name[32]; //返回用户名 }RET_T;
int main(int argc, char* argv[]) { int socket_fd; int ret; char buff[1024]; char buffer[1024]; int lens; int recv_len; int sent_len; unsigned char recv_buf[1000]; int client_num = -1; socklen_t addr_len; int new_fd; signal(SIGCHLD, SIG_IGN);//防止僵尸进程产生 socket_fd = socket(AF_INET, SOCK_STREAM, 0); struct sockaddr_in server_addr; struct sockaddr_in client_addr; if (-1 == socket_fd) { fprintf(stderr, “socket error %s\n”, strerror(errno)); // rerror exit(1); } int issockeopet = 1; if (setsockopt(socket_fd, SOL_SOCKET, SO_REUSEADDR, (const char*)&issockeopet, sizeof(int)) < 0)//设置ip地址重复使用 { close(socket_fd); exit(1); } memset(&server_addr, 0, sizeof(struct sockaddr_in)); server_addr.sin_family = AF_INET; server_addr.sin_port = htons(8888); server_addr.sin_addr.s_addr = htonl(INADDR_ANY);//自动接受任意IP地址
ret = bind(socket_fd, (struct sockaddr*)(&server_addr), sizeof(struct sockaddr));
if (ret == -1)
{
fprintf(stderr, "bind error:%s\n", strerror(errno));
exit(0);
}
if (listen(socket_fd, 10) == -1)
{
fprintf(stderr, "listen error:%s\n", strerror(errno));
exit(0);
}
//数据包定义
char BackData[128] = { 0 };
HEAD_T* read_head = (HEAD_T*)malloc(sizeof(HEAD_T)); //用户数据包头
USER_T* read_user = (USER_T*)malloc(sizeof(USER_T)); //用户数据包体
HEAD_T* ret_head = (HEAD_T*)malloc(sizeof(HEAD_T)); //服务应答数据包头
RET_T* ret_info = (RET_T*)malloc(sizeof(RET_T));
/* accept */
while (1)
{
addr_len = sizeof(struct sockaddr);
new_fd = accept(socket_fd, (struct sockaddr*)&client_addr, &addr_len);
if (-1 == new_fd)
{
fprintf(stderr, "accept error:%s\n\a", strerror(errno));
close(socket_fd);
exit(1);
}
client_num++;
fprintf(stderr, "Server get connetion form client%d: %s\n", client_num, inet_ntoa(client_addr.sin_addr));
if (!fork())
{
/* Child process */
printf("hello world!");
while (1)
{
/* recv */
recv_len = recv(new_fd, recv_buf, 1024, 0);
printf("%d", recv_len);
if (recv_len <= 0)
{
fprintf(stderr, "recv error:%s\n\a", strerror(errno));
close(new_fd);
exit(1);
}
else
{
memcpy(read_head, recv_buf, sizeof(HEAD_T));
memcpy(read_user, recv_buf + sizeof(HEAD_T), sizeof(USER_T));
printf("nbytes is %d\n", recv_len);
printf("fun is %d\n", read_head->fun);
printf("UserName is %s \nPassWord is %s\n", read_user->UserName, read_user->PassWord);
memset(read_head, 0, sizeof(read_head));
//if (strcmp(read_user->UserName, "admin") == 0 and strcmp(read_user->PassWord, "123456") == 0)
//{
// ret_info->flag = 1;//1表示登录成功
// strcpy(ret_info->name, read_user->UserName);
// ret_head->dataLength = 0;
// ret_head->fun = 1;
// memset(buffer, 0, 1024);
// memcpy(buffer, &ret_head, sizeof(HEAD_T));
// memcpy(buffer + sizeof(RET_T), &ret_info, sizeof(USER_T));
// int nbytes = ::write(new_fd, buffer, sizeof(RET_T)+ sizeof(USER_T));
//}
}
}
close(new_fd);
}
}
/* close */
close(socket_fd);
exit(0);
return 0;
} 客户端qt处理数据发包 char buffer[1024]; HEAD_T login_head; USER_T login_data; login_head.fun=LOGIN_IN; login_head.dataLength=sizeof(HEAD_T)+sizeof(USER_T); strcpy(login_data.UserName,ui->lineEdit->text().toStdString().c_str()); strcpy(login_data.PassWord,ui->lineEdit_2->text().toStdString().c_str()); memset(buffer,0,1024); memcpy(buffer,&login_head,sizeof(HEAD_T)); memcpy(buffer+sizeof(HEAD_T),&login_data,sizeof(USER_T)); int nbytes=::write(settingWin::sock_fd,buffer,sizeof(HEAD_T)+sizeof(USER_T)); qDebug()<<nbytes<<endl; qDebug()<<“socket is %d”<<settingWin::sock_fd<<endl;
总结
提示:这里对文章进行总结: 本次我用开启第二个线程的办法进行操作,之后会改成进程后期变成线程池
|