C++开发服务器2

提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档

内容


服务器升级版,获取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;

总结

提示:这里对文章进行总结:
本次我用开启第二个线程的办法进行操作,之后会改成进程后期变成线程池

おすすめ

転載: blog.csdn.net/qq_46418241/article/details/121895275