前往小程序,Get更优阅读体验!
立即前往
发布
社区首页 >专栏 >Socket网络通信之发送数据包

Socket网络通信之发送数据包

作者头像
看、未来
发布2020-08-26 10:47:43
发布2020-08-26 10:47:43
1.6K00
代码可运行
举报
运行总次数:0
代码可运行

22.1 本篇Socket 发送数据包的具体格式

鉴于我被那些吹牛皮的浪费一下午的时间的惨痛经历,我就明说了,我这篇是基于结构体形式的、客户端请求服务器的、服务器接收并发送应答包的,一篇博客。 如果不是你所需要的,可以换别篇了。

22.2 代码设计

我哪个栗子吧,登录注册请求服务端应答的栗子。

当然会有更好的方法来设计

首先,需要来个表明目的的结构体,你是要干嘛,登录、注册,还是就找回密码啊或者其他的。 typedef struct pub_head { int fun;//发出的 0链接 1:登录 2:注册 3:找回密码 (其他再说吧,目前没想到) }HEAD_T;

然后就需要一个请求包的结构体了,需要用户名、密码,或者还有啥其他的 typedef struct login_t { char username[25]; char passwd[25]; //其他再说吧 }LOGIN_M;

接下来再来一个回应包 typedef struct login_res { int flag; // 连接状态 1成功 0 失败 char usernaem[25]; char time[30]; }LOGIN_S; //服务器返回

嗯,一个粗略的数据包外壳包好了,该填东西了。

22.3 代码

客户端是用QT写的,前面谈过的内容就不赘述了,主要是这一块

代码语言:javascript
代码运行次数:0
复制
        socket->abort();
        socket->connectToHost(IP_now,PORN_now.toInt());
        
        HEAD_T head;
        head.fun=1;
        
        LOGIN_M login;
        QByteArray name =this->NameEdit->text().toLatin1();
        QByteArray pwd =this->PwdEdit->text().toLatin1();
        strcpy(login.username,name.data());
        strcpy(login.passwd,pwd.data());
        
        char *data=new char[1024];
        memcpy(data,&head,sizeof(HEAD_T));
        memcpy(data+sizeof(HEAD_T),&login,sizeof(LOGIN_M));
        socket->write(data,sizeof(HEAD_T)+sizeof(LOGIN_M));

服务端代码是放在Linux底下跑的C 伪代码,主要是为了突出解包及应答包

代码语言:javascript
代码运行次数:0
复制
#include <stdlib.h>
#include <stdio.h>  
#include <errno.h>  
#include <string.h>  
#include <netdb.h>  
#include <sys/types.h>  
#include <netinet/in.h>  
#include <sys/socket.h>    
#include "sqlite3.h"

#define portnumber //端口号,自己设置   

int main(int argc, char *argv[])
{   	
	//截取字符串
	HEAD_T head;
	LOGIN_M login_m;
	LOGIN_S login_s;
	char data[1024];
	int num = 0;
	int nbytes;  
	char buffer[1024];
	
   	 char *errMsg;
   	 int rc;

	
	//设置Socket属性:SO_REUSEADDR:允许在bind过程中本地地址重复使用   
	int iSockopt = 1;
	if (setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, 
		(const char *)&iSockopt, sizeof(int)) < 0 )
	{   
		close(sockfd);   
		return -1;   
	}
	
	while(1)   
	{    
		/* 服务器阻塞,直到客户程序建立连接 */    
		sin_size=sizeof(struct sockaddr_in);    
		if((new_fd=accept(sockfd,(struct sockaddr *)(&client_addr),&sin_size))==-1)    
		{     
			fprintf(stderr,"Accept error:%s\n\a",strerror(errno));     
			exit(1);    
		}    
		fprintf(stderr,"Server get connection from %s\n",inet_ntoa(client_addr.sin_addr)); // 将网络地址转换成.字符串
		
		
		if((nbytes=read(new_fd,buffer,1024))==-1)    
		{     	
			printf("%d",nbytes);
			fprintf(stderr,"Read Error:%s\n",strerror(errno));     
			exit(1);    
		} 
		
		//下面开始解包
		buffer[nbytes]='\0'; 
		ptr = buffer;
		memcpy(&head,ptr,sizeof(HEAD_T));
		num=head.fun;

   		switch(num)
		{
			case 0://确定连上服务器
				{
					login_s.flag=1;
					printf("\ncase=%d\n",num);
					 memcpy(data,&head,sizeof(HEAD_T));
					 memcpy(data+sizeof(HEAD_T),&login_s,sizeof(login_s));
					write(new_fd,data,sizeof(login_s)+sizeof(head)); 
					memset(data,0,sizeof(data));
					memset(buffer,0,sizeof(buffer));
					memset(&login_s,0,sizeof(login_s));
					//memset(login_m,0,sizeof(login_m));
					ptr=NULL;
					
					
				}
			break;
			case 1://登录
				printf("\ncase=%d\n",num);
				memcpy(&login_m,ptr+sizeof(HEAD_T),sizeof(LOGIN_M));
				sprintf(sql,"select * from user where name = '%s'and pwd = '%s'",
				login_m.username,login_m.passwd);
				rc = sqlite3_get_table(db,sql,&dbResult,&nRow,&nColumn,&errMsg);
				if(rc == SQLITE_OK && nRow == 1)	
				{		
					login_s.flag=1;
					//printf("fun=%d",head.fun);
 					memcpy(data,&head,sizeof(HEAD_T));
					memcpy(data+sizeof(HEAD_T),&login_s,sizeof(login_s));
					write(new_fd,data,sizeof(login_s)+sizeof(head)); 
					printf("\nlogin succse\n");
					
				}
				else if(rc != SQLITE_OK || nRow != 1)	
				{		
					login_s.flag=0;
 					memcpy(data,&head,sizeof(HEAD_T));
					memcpy(data+sizeof(HEAD_T),&login_s,sizeof(login_s));
					write(new_fd,data,sizeof(data));
					printf("\nlocin error");  
					
				}
			ptr=NULL;
			break;
			case 2://
				printf("case=%d\n",num);
				memcpy(&login_m,ptr+sizeof(HEAD_T),sizeof(LOGIN_M));
				sprintf(sql,"insert into user values ('%s','%s',0,'0','0')",
				login_m.username,login_m.passwd);
				rc = sqlite3_get_table(db,sql,&dbResult,&nRow,&nColumn,&errMsg);
				if(rc==SQLITE_OK)
					printf(" \nadd success\n");
			ptr=NULL;
				break; 
			
			case 3://
				printf("case=%d\n",num);
				memcpy(&login_m,ptr+sizeof(HEAD_T),sizeof(LOGIN_M));
				printf("admin=%s,pwd=%s",login_m.username,login_m.passwd);
				sprintf(sql,"update user set pwd = '%s' where name = '%s'",
				login_m.passwd,login_m.username);
				rc = sqlite3_get_table(db,sql,&dbResult,&nRow,&nColumn,&errMsg);
				if(rc==SQLITE_OK)
					printf("\n updata success\n");
			ptr=NULL;
				break; 
		}
  
		printf("\nServer received %s\n",buffer);      //这个通讯已经结束     
	
		close(new_fd);    /* 循环下一个 */   
	}    /* 结束通讯 */
	
	close(sockfd);   
	exit(0);  
}

当时我做雷霆战机的时候,看得我是一脸懵逼。。。 现在拿这个我能看的明白还能上注解了

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2020/01/20 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 22.1 本篇Socket 发送数据包的具体格式
    • 22.2 代码设计
    • 22.3 代码
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档