一,粘包
原因:tcp为流式套接字,数据与数据间没有边界,导致多次数据粘到一起。
解决:
1.规定一些数据间的间隔符,"\aa","\r\n";
2.可以指定要发送对象的数据长度。
3.自己将数据打包。
1.上传接收粘连
1.用户端
cpp
#include <head.h>
int connect_server(const char *ip,const char *port)
{
int fd = socket(AF_INET,SOCK_STREAM,0);
if (fd < 0)
handle_error_ret("socket fail");
struct sockaddr_in seraddr;
memset(&seraddr,0,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = inet_addr(ip);
seraddr.sin_port = htons(atoi(port));//"50000"
if (connect(fd,(const struct sockaddr *)&seraddr,sizeof(seraddr)) < 0)
handle_error_ret("connect_server fail");
return fd;
}
//./cli 127.0.0.1 50000 filename
int main(int argc, const char *argv[])
{
if (argc != 4)
{
printf("usage: %s <ip> <port> <filename>\n",argv[0]);
return -1;
}
int fd = connect_server(argv[1],argv[2]);
if (fd < 0)
return -1;
int fd_s = open(argv[3],O_RDONLY);
if (fd_s < 0)
handle_error_ret("open fail");
write(fd,argv[3],strlen(argv[3])+1);
// write(fd,argv[3],strlen(argv[3]));
char buf[100] = {0};
int ret = 0;
while (1)
{
ret = read(fd_s,buf,sizeof(buf));
if (ret == 0)
break;
write(fd,buf,ret);
}
close(fd_s);
close(fd);
return 0;
}
2.服务器
cpp
#include <head.h>
int init_server(const char *ip,const char *port)
{
int fd = socket(AF_INET,SOCK_STREAM,0);
if (fd < 0)
handle_error_ret("socket fail");
struct sockaddr_in seraddr;
memset(&seraddr,0,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = inet_addr(ip);
seraddr.sin_port = htons(atoi(port));//"50000"
if (bind(fd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
handle_error_ret("bind fail");
if (listen(fd,5) < 0)
handle_error_ret("listen fail");
return fd;
}
//./ser 127.0.0.1 50000
int main(int argc, const char *argv[])
{
int ret = 0;
if (argc != 3)
{
printf("Usage: %s <ip> <port>\n",argv[0]);
return -1;
}
int listenfd = init_server(argv[1],argv[2]);
if (listenfd < 0)
return -1;
int connfd = 0;
if ((connfd = accept(listenfd,NULL,NULL)) < 0)
handle_error_ret("accept fail");
//读文件名
char buf[100] = {0};
ret = read(connfd,buf,sizeof(buf));
printf("ret = %d buf = %s\n",ret, buf);
int fd_d = open(buf,O_WRONLY|O_CREAT|O_TRUNC,0666);
if (fd_d < 0)
handle_error_ret("open fail");
while (1)
{
ret = read(connfd,buf,sizeof(buf));
printf("ret = %d buf1 = %s \n",ret,buf);
if (ret == 0)
break;
write(fd_d,buf,ret);
}
close(fd_d);
close(connfd);
return 0;
}
3.注意
服务器和客户端不能写在同级别文件夹中
2.解决粘连
1.客户端
cpp
#include <head.h>
int connect_server(const char *ip,const char *port)
{
int fd = socket(AF_INET,SOCK_STREAM,0);
if (fd < 0)
handle_error_ret("socket fail");
struct sockaddr_in seraddr;
memset(&seraddr,0,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = inet_addr(ip);
seraddr.sin_port = htons(atoi(port));//"50000"
if (connect(fd,(const struct sockaddr *)&seraddr,sizeof(seraddr)) < 0)
handle_error_ret("connect_server fail");
return fd;
}
//./cli 127.0.0.1 50000 filename
int main(int argc, const char *argv[])
{
if (argc != 4)
{
printf("usage: %s <ip> <port> <filename>\n",argv[0]);
return -1;
}
int fd = connect_server(argv[1],argv[2]);
if (fd < 0)
return -1;
int fd_s = open(argv[3],O_RDONLY);
if (fd_s < 0)
handle_error_ret("open fail");
//write(fd,argv[3],strlen(argv[3])+1);
write(fd,argv[3],strlen(argv[3]));
//方式1
//sleep(1);
//方式2
write(fd,"\r\n",2);
char buf[100] = {0};
int ret = 0;
while (1)
{
ret = read(fd_s,buf,sizeof(buf));
if (ret == 0)
break;
write(fd,buf,ret);
}
close(fd_s);
close(fd);
return 0;
}
2.服务器
cpp
#include <head.h>
int init_server(const char *ip,const char *port)
{
int fd = socket(AF_INET,SOCK_STREAM,0);
if (fd < 0)
handle_error_ret("socket fail");
struct sockaddr_in seraddr;
memset(&seraddr,0,sizeof(seraddr));
seraddr.sin_family = AF_INET;
seraddr.sin_addr.s_addr = inet_addr(ip);
seraddr.sin_port = htons(atoi(port));//"50000"
if (bind(fd,(const struct sockaddr*)&seraddr,sizeof(seraddr)) < 0)
handle_error_ret("bind fail");
if (listen(fd,5) < 0)
handle_error_ret("listen fail");
return fd;
}
//./ser 127.0.0.1 50000
int main(int argc, const char *argv[])
{
int ret = 0;
if (argc != 3)
{
printf("Usage: %s <ip> <port>\n",argv[0]);
return -1;
}
int listenfd = init_server(argv[1],argv[2]);
if (listenfd < 0)
return -1;
int connfd = 0;
if ((connfd = accept(listenfd,NULL,NULL)) < 0)
handle_error_ret("accept fail");
//读文件名
char buf[100] = {0};
FILE *fp = fdopen(connfd,"r");
if (fp == NULL)
handle_error_ret("fdopen fail");
fgets(buf,sizeof(buf),fp); //buf => 1.txt\r\n
buf[strlen(buf)-2] = '\0';
// ret = read(connfd,buf,sizeof(buf));
// printf("ret = %d buf = %s\n",ret, buf);
printf("buf = %s\n",buf);
int fd_d = open(buf,O_WRONLY|O_CREAT|O_TRUNC,0666);
if (fd_d < 0)
handle_error_ret("open fail");
while (1)
{
//ret = read(connfd,buf,sizeof(buf));
ret = fread(buf,1,sizeof(buf),fp);
printf("ret = %d buf1 = %s \n",ret,buf);
if (ret == 0)
break;
write(fd_d,buf,ret);
}
close(fd_d);
close(connfd);
return 0;
}
3.recv send函数(仅用于TCP中)
1.recv 类似于read函数

用法

比read函数多一个参数,仅用于TCP中
2.send 类似于write函数

send recv函数最后一个参数即允许非阻塞操作。
二,telnet,SSH,wireshark
1.telent
1.在windows中
telent可以在windows上用cmd创建一个linux,需要在linux中用ifconfig查看ip地址即可

linux IP为 192.168.11.128


2.第三方软件

以他实例

选择Telnet,输入IP

2.SSH
功能与telnet类似,只是传输过程加密
3.wireshark 抓包工具 抓取网络上数据
1.抓取telnet
输入指令打开



红色输入蓝色输出
2.抓取SSH

加密了
三次招手与四次挥手



3.wireshark中的命令
