Socket网络通信之发送数据包
时间:2022-07-23
本文章向大家介绍Socket网络通信之发送数据包,主要内容包括其使用实例、应用技巧、基本知识点总结和需要注意事项,具有一定的参考价值,需要的朋友可以参考一下。
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写的,前面谈过的内容就不赘述了,主要是这一块
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 伪代码,主要是为了突出解包及应答包
#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:%sna",strerror(errno));
exit(1);
}
fprintf(stderr,"Server get connection from %sn",inet_ntoa(client_addr.sin_addr)); // 将网络地址转换成.字符串
if((nbytes=read(new_fd,buffer,1024))==-1)
{
printf("%d",nbytes);
fprintf(stderr,"Read Error:%sn",strerror(errno));
exit(1);
}
//下面开始解包
buffer[nbytes]=' ';
ptr = buffer;
memcpy(&head,ptr,sizeof(HEAD_T));
num=head.fun;
switch(num)
{
case 0://确定连上服务器
{
login_s.flag=1;
printf("ncase=%dn",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=%dn",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 succsen");
}
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=%dn",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 successn");
ptr=NULL;
break;
case 3://
printf("case=%dn",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 successn");
ptr=NULL;
break;
}
printf("nServer received %sn",buffer); //这个通讯已经结束
close(new_fd); /* 循环下一个 */
} /* 结束通讯 */
close(sockfd);
exit(0);
}
当时我做雷霆战机的时候,看得我是一脸懵逼。。。 现在拿这个我能看的明白还能上注解了
- JavaScript 教程
- JavaScript 编辑工具
- JavaScript 与HTML
- JavaScript 与Java
- JavaScript 数据结构
- JavaScript 基本数据类型
- JavaScript 特殊数据类型
- JavaScript 运算符
- JavaScript typeof 运算符
- JavaScript 表达式
- JavaScript 类型转换
- JavaScript 基本语法
- JavaScript 注释
- Javascript 基本处理流程
- Javascript 选择结构
- Javascript if 语句
- Javascript if 语句的嵌套
- Javascript switch 语句
- Javascript 循环结构
- Javascript 循环结构实例
- Javascript 跳转语句
- Javascript 控制语句总结
- Javascript 函数介绍
- Javascript 函数的定义
- Javascript 函数调用
- Javascript 几种特殊的函数
- JavaScript 内置函数简介
- Javascript eval() 函数
- Javascript isFinite() 函数
- Javascript isNaN() 函数
- parseInt() 与 parseFloat()
- escape() 与 unescape()
- Javascript 字符串介绍
- Javascript length属性
- javascript 字符串函数
- Javascript 日期对象简介
- Javascript 日期对象用途
- Date 对象属性和方法
- Javascript 数组是什么
- Javascript 创建数组
- Javascript 数组赋值与取值
- Javascript 数组属性和方法
- 浙大版《C语言程序设计(第3版)》题目集 习题4-10 猴子吃桃问题
- 6种展示代码的绝佳方式
- 你电脑里的IE浏览器正在被黑客利用
- 浙大版《C语言程序设计(第3版)》题目集 习题6-8 统计一行文本的单词个数
- 浙大版《C语言程序设计(第3版)》题目集 练习7-2 求最大值及其下标
- 浙大版《C语言程序设计(第3版)》题目集 练习7-3 将数组中的数逆序存放
- CycleGan人脸转为漫画脸,牛掰的知识又增加了!| 附代码
- 浙大版《C语言程序设计(第3版)》题目集 练习7-4 找出不是两个数组共有的元素
- 浙大版《C语言程序设计(第3版)》题目集 练习7-7 矩阵运算
- 系统之眼!Linux系统性能监控工具Glances
- 浙大版《C语言程序设计(第3版)》题目集 练习7-8 方阵循环右移
- 浙大版《C语言程序设计(第3版)》题目集 练习7-9 计算天数
- 浙大版《C语言程序设计(第3版)》题目集 练习7-10 查找指定字符
- 浙大版《C语言程序设计(第3版)》题目集 练习7-11 字符串逆序
- 浙大版《C语言程序设计(第3版)》题目集 习题7-1 选择法排序