您现在的位置是:首页 >其他 >Linux 学习记录31(网络编程篇)网站首页其他
Linux 学习记录31(网络编程篇)
简介Linux 学习记录31(网络编程篇)
Linux 学习记录31(网络编程篇)
本文目录
一、UDP中的connect函数
udp中也可以使用connect函数
- TCP中的connect函数会连接服务器,产生三次握手,将服务器和客户端连接起来。
- UDP中的connect不会产生连接,仅仅是将对端的IP和端口号记录到内核套接字中。此时UDP只能与记录的对端进行通信
- 记录后只能与记录的端口和IP进行通信
- 在TCP中这个函数只能成功一次,代表连接服务器
- 而在UDP中这个函数可以成功多次,前一次写入的端口和IP会被后一次的覆盖
- 若想清空内核数据,只要将sa_family 改成AF_UNSPEC,来清空内核中对端的内核信息
- 当UDP采用他connect方式手法数据后recvfrom后面参数改为NULL,sendof后面参数改为,NULL和0;
UDP调用connect的优点
- 提升传输效率
- 不调用:将对端的信息填充到内核->发送报文->清空内核信息->将对端的信息填充到内核->发送报文->清空内核信息
- 调用:将对端的信息填充到内核->发送报文->发送报文->发送报文->清空内核信息
- 增加传输稳定性
- 调用connet的udp通信,可以防止AB进程在传输数据的过程中收到C的数据,造成数据错误
1. 绑定客户端
struct sockaddr_in dstaddr;
dstaddr.sin_family = AF_INET;
/*记录指定的端口号和IP*/
dstaddr.sin_port = htons(6666);
dstaddr.sin_addr.s_addr = inet_addr("192.168.2.56");
if(connect(sfd, (struct sockaddr *)&dstaddr, sizeof(dstaddr)) == -1)
{/*记录IP和端口号到套接字内核中*/
ERR_MSG("connect");
return -1;
}//记录完成后将只能接收来自记录的IP和端口的数据
2. 解绑客户端
struct sockaddr_in dstaddr;
dstaddr.sin_family = AF_UNSPEC;//清空内核中对端的内核信息
if(connect(sfd, (struct sockaddr *)&dstaddr, sizeof(dstaddr)) == -1)
{/*记录IP和端口号到套接字内核中*/
ERR_MSG("connect");
return -1;
}//记录完成后将只能接收来自记录的IP和端口的数据
二、(扩展)直接读取键盘值
1. 找到键盘的驱动文件
目录:
2. 找到使用的键盘的驱动文件
sudo cat event文件
"当打开文件后操作键盘如果看到有数据读出就是该键盘对应的文件"
3. 读取文件
由于文件在根目录,所以运行程序需要+sudo
//打开键盘驱动文件
int fd = open("/dev/input/event1", O_RDONLY);
if(fd < 0)
{
ERR_MSG("open");
return -1;
}
printf("open success fd=%d
", fd);
//读取键盘驱动文件中的数据, /dev/input/event1
struct input_event ev;
while(1)
{
if(read(fd, &ev, sizeof(ev)) <= 0)
{
ERR_MSG("read");
return -1;
}
printf("ev.type:%u ev.code:%u ev.value:%d
", ev.type, ev.code, ev.value);
}
练习通过Tfpd32软件的文件上传与下载
1. main.c
#include "public.h"
int main(int argc, char const *argv[])
{
int menu_num = 0;
int power = 1;
time_t sys_t = time(NULL);
struct tm *fomattime = localtime(&sys_t);
char time_str[50] = {0};
char buf1[50] = {0};
char buf2[50] = {0};
char ch1 = 0;
int back = 0;
umask(0);
/*发送请求*/
// send_request(RD,"file01i1.txt","octet");
/*创建报式套接字*/
int sfd = socket(AF_INET, SOCK_DGRAM, 0);
printf("创建报式套接字...
");
if(sfd < 0)
{//如果创建失败则
ERR_MSG("socket");
return -1;
}
printf("创建成功
");
/*允许端口被快速重用*/
int reuse = 1;
if(setsockopt(sfd,SOL_SOCKET,SO_REUSEADDR,&reuse,sizeof(reuse)))
{
ERR_MSG("setsockopt");
return -1;
}
/*绑定绑定服务器IP和端口到文件描述付*/
struct sockaddr_in cin_addr;
char server_IP[20] = "192.168.2.54";//存储服务器IP
int server_port = 69;//存储服务器端口
cin_addr.sin_family = AF_INET;
printf("input server IP : %s
", server_IP);
// fgets(server_IP, sizeof(server_IP),stdin);//获取服务器IP
printf("input server port : %d
", server_port);
// scanf("%d",&server_port);//获取服务器端口
cin_addr.sin_addr.s_addr = inet_addr(server_IP);
cin_addr.sin_port = htons(server_port);
/*接收消息*/
socklen_t cin_len = sizeof(cin_addr);
char str[128];
char buf[128];
int res = 0;
printf("客户端已打开
");
while(power)
{
printf("请选择你的功能:
");
menu();
scanf("%d",&menu_num);
switch(menu_num)
{
case 1:{
printf("请输入需要下载的文件名: ");
scanf("%s",buf1);
printf("是否将下载的文件重命名[y/n]: ");
scanf("
%c",&ch1);
if(ch1 == 'y')
{
printf("请输入重命名的文件名: ");
scanf("
%s",buf2);
printf("下载文件:%s----->%s
",buf1,buf2);
back = down_load(buf1,buf2,sfd,cin_addr);
}else if(ch1 == 'n')
{
printf("下载文件:%s----->%s
",buf1,buf1);
back = down_load(buf1,NULL,sfd,cin_addr);
}
if(back == 0)
{
printf("下载完成
");
}else if(back == -1)
{
printf("下载失败
");
}
}break;
case 2:{
printf("是否查看文件库目录[y/n]
");
scanf("
%c",&ch1);
if(ch1 == 'y') view_file_lib();
printf("请输入要上传的文件
");
scanf("
%s",buf1);
printf("是否将上传后的文件重命名[y/n]: ");
scanf("
%c",&ch1);
if(ch1 == 'y')
{
printf("请输入重命名的文件名: ");
scanf("
%s",buf2);
printf("上传文件:%s----->%s
",buf1,buf2);
back = up_load(buf1,buf2,sfd,cin_addr);
}else if(ch1 == 'n')
{
printf("上传文件:%s----->%s
",buf1,buf1);
back = up_load(buf1,NULL,sfd,cin_addr);
}
if(back == 0)
{
printf("上传完成
");
}else if(back == -1)
{
printf("上传失败
");
}
}break;
// case 3:{
// printf("查看文件库
");
// system(FILE_LIB);
// }break;
case 3:{
printf("退出客户端
");
power = 0;
}break;
default:{
printf("请重新输入
");
}break;
}
}
close(sfd);
return 0;
}
2. public.h
#ifndef __PUBLIC_H_
#define __PUBLIC_H_
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#include <stdarg.h>
#include <unistd.h>
#include <errno.h>
#include <time.h>
#include <fcntl.h>
#include <dirent.h>
#include <pthread.h>
#include <semaphore.h>
#include <signal.h>
#include <sys/ipc.h>
#include <sys/msg.h>
#include <sys/shm.h>
#include <sys/wait.h>
#include <sys/stat.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
#define R O_RDONLY
#define W O_WRONLY|O_CREAT|O_TRUNC
#define A O_WRONLY|O_CREAT|O_APPEND
#define Rp O_RDWR
#define Wp O_RDWR|O_CREAT|O_TRUNC
#define Ap O_RDWR|O_CREAT|O_APPEND
#define IP "192.168.2.52"
#define PORT 8080
#define BACKLOG 128
#define RD 0x01
#define WR 0x02
#define FILE_LIB "./file_lib/" //当前目录下的文件库
/*输入打印的错误类型 打印错误信息,行,具体函数*/
#define ERR_MSG(msg) do{
fprintf(stderr, "Line:%d :%s %s
",__LINE__, __FILE__,__func__);
perror(msg);
}while(0)
/*获取时间戳*/
#define GET_TIME(str) do{
time_t sys_t = time(NULL);
struct tm *fomattime = localtime(&sys_t);
sprintf(str,"[%.4d-%.2d-%.2d %.2d:%.2d:%.2d]",
fomattime->tm_year+1900,fomattime->tm_mon+1,fomattime->tm_mday,
fomattime->tm_hour,fomattime->tm_min,fomattime->tm_sec);
}while(0)
#pragma pack(1) //设置默认对齐系数 :() 中的参数只能填2^n (n=0,1,2,3,4,5......)
typedef struct
{
int num;//包编号
int buf_len;//包长
char buf_data[1024];//包数据
}a;
/*选项菜单*/
void menu(void);
/*发送请求*/
void send_request(char Opcode,const char* file_nume,const char* mode,int sfd,struct sockaddr_in cin_addr);
/*下载*/
int down_load(const char* file_name,const char* new_name,int sfd,struct sockaddr_in cin_addr);
/*查看文件文件库*/
void view_file_lib(void);
/*上传*/
int up_load(const char* file_name,const char* new_name,int sfd,struct sockaddr_in cin_addr);
#endif
3. public.c
#include "public.h"
/*应答,0-1:操作码,固定4,2-3:块编号*/
uint8_t ACK[4] = {0X00,0X04,0X00,0X00};
/*选项菜单*/
void menu(void)
{
printf("**************************************
");
printf("1. 下载文件 | 2. 上传文件 | 3.退出客户端|
");
printf("**************************************
");
}
/*发送请求*/
void send_request(char Opcode,const char* file_nume,const char* mode,int sfd,struct sockaddr_in cin_addr)
{
uint8_t buf[128] = {0};//发送数据缓存
int len = strlen(file_nume);
socklen_t cin_len = sizeof(cin_addr);
buf[0] = 0x00;
buf[1] = Opcode;//操作码
strcpy(buf+2,file_nume);//文件名
len+=2;
buf[len++] = 0x00;//'