This commit is contained in:
parent
dd22bec895
commit
5cdb1cc311
Binary file not shown.
After Width: | Height: | Size: 31 KiB |
Binary file not shown.
|
@ -0,0 +1,95 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <fcntl.h>
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/stat.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
./a.out server_ip 下载的文件名
|
||||||
|
*/
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
if (argc != 3)
|
||||||
|
{
|
||||||
|
printf("usage: %s server_ip filename\n", argv[0]);
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
int sock_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (sock_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct stat st;
|
||||||
|
stat(argv[2], &st);
|
||||||
|
int tsize = st.st_size;
|
||||||
|
// 生成请求数据包
|
||||||
|
char request[64];
|
||||||
|
// char *tsize = 0;
|
||||||
|
int request_size = sprintf(request, "%c%c%s%c%s%c%d%c", 0, 1, argv[2], 0, "octet", 0, tsize, 0);
|
||||||
|
|
||||||
|
// 发送请求
|
||||||
|
struct sockaddr_in server_addr;
|
||||||
|
bzero(&server_addr, sizeof(server_addr));
|
||||||
|
server_addr.sin_family = AF_INET;
|
||||||
|
server_addr.sin_port = htons(69); // 服务器TFTP端口
|
||||||
|
server_addr.sin_addr.s_addr = inet_addr(argv[1]); // 服务器地址
|
||||||
|
|
||||||
|
sendto(sock_fd, request, request_size, 0, (struct sockaddr *)&server_addr, sizeof(server_addr));
|
||||||
|
|
||||||
|
char buf[516] = "";
|
||||||
|
struct sockaddr_in data_addr;
|
||||||
|
socklen_t data_addr_len = sizeof(data_addr);
|
||||||
|
bzero(&data_addr, sizeof(data_addr));
|
||||||
|
ssize_t len = recvfrom(sock_fd, buf, 516, 0, (struct sockaddr *)&data_addr, &data_addr_len);
|
||||||
|
|
||||||
|
// 验证接收的数据是否是 OK
|
||||||
|
if (buf[1] == 3)
|
||||||
|
{
|
||||||
|
// printf("收到的文件大小为 %d\n", tsize);
|
||||||
|
// 创建本地文件的描述符(打开或创建文件)
|
||||||
|
int fd = open(argv[2], O_CREAT | O_WRONLY, 0666);
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
printf("文件名为 %s,文件大小为 %s\n", argv[2], buf + 2);
|
||||||
|
|
||||||
|
// 收到的是数据报
|
||||||
|
write(fd, buf + 4, len - 4);
|
||||||
|
// 回ACK
|
||||||
|
buf[1] = 4;
|
||||||
|
// buf[2] = "tsize";
|
||||||
|
sendto(sock_fd, buf, 4, 0, (struct sockaddr *)&data_addr, sizeof(data_addr));
|
||||||
|
if (len < 516)
|
||||||
|
{
|
||||||
|
printf("数据接收完成\n");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
bzero(&data_addr, data_addr_len);
|
||||||
|
bzero(buf, sizeof(buf));
|
||||||
|
len = recvfrom(sock_fd, buf, 516, 0, (struct sockaddr *)&data_addr, &data_addr_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(fd);
|
||||||
|
}
|
||||||
|
else if (buf[1] == 5)
|
||||||
|
{
|
||||||
|
// 收到的是错误信息
|
||||||
|
printf("error: %s\n", buf + 4);
|
||||||
|
}
|
||||||
|
// else if (buf[1] == 6)
|
||||||
|
// {
|
||||||
|
// // 收到OACK包,包含请求选项回传的值
|
||||||
|
// printf("文件名为 %s,文件大小为 %s\n", argv[2], buf + 2);
|
||||||
|
// }
|
||||||
|
|
||||||
|
close(sock_fd);
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,196 @@
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <pthread.h>
|
||||||
|
|
||||||
|
#define BUFFLEN 1024 //缓冲区的大小
|
||||||
|
#define SERVER_PORT 1235 //端口号
|
||||||
|
#define HTTP_FILENAME_LEN 256
|
||||||
|
|
||||||
|
struct doc_type
|
||||||
|
{
|
||||||
|
char *suffix;
|
||||||
|
char *type;
|
||||||
|
};
|
||||||
|
//返回内容对应 MIME 类型
|
||||||
|
struct doc_type file_type[] =
|
||||||
|
{
|
||||||
|
{ "html", "text/html" },
|
||||||
|
{ "ico", "image/x-icon" },
|
||||||
|
{ NULL, NULL }
|
||||||
|
};
|
||||||
|
void * threadFun(void * args);
|
||||||
|
void handle_connect(int serv_sock);
|
||||||
|
void http_parse_request_cmd(char *buf,char *file_name, char *suffix);
|
||||||
|
char *http_get_type_by_suffix(const char *suffix);
|
||||||
|
|
||||||
|
char *http_res_hdr_tmpl = "HTTP/1.1 200 OK\nServer: bianchengbang\n"
|
||||||
|
"Accept-Ranges: bytes\nContent-Length: %d\nConnection: closed\n"
|
||||||
|
"Content-Type: %s\n\n";
|
||||||
|
|
||||||
|
int main() {
|
||||||
|
int serv_sock;
|
||||||
|
struct sockaddr_in serv_addr;
|
||||||
|
//创建套接字
|
||||||
|
if ((serv_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP)) == -1) {
|
||||||
|
printf("套接字创建失败\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//将套接字与任意 IP 地址和 1234 端口进行绑定
|
||||||
|
memset(&serv_addr, 0, sizeof(serv_addr));
|
||||||
|
serv_addr.sin_family = AF_INET;
|
||||||
|
serv_addr.sin_addr.s_addr = htonl(INADDR_ANY);
|
||||||
|
serv_addr.sin_port = htons(SERVER_PORT);
|
||||||
|
if (bind(serv_sock, (struct sockaddr*)&serv_addr, sizeof(serv_addr)) == -1) {
|
||||||
|
close(serv_sock);
|
||||||
|
printf("bind()执行失败\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
//让套接字进入被动监听状态
|
||||||
|
if (listen(serv_sock, SOMAXCONN) == -1) {
|
||||||
|
close(serv_sock);
|
||||||
|
printf("listen()执行失败\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
|
||||||
|
handle_connect(serv_sock);
|
||||||
|
close(serv_sock);
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
void handle_connect(int serv_sock){
|
||||||
|
int clnt_sock;
|
||||||
|
struct sockaddr_in clnt_addr;
|
||||||
|
socklen_t clnt_addr_size = sizeof(clnt_addr);
|
||||||
|
//死循环,持续不断地接收任意客户端发来的请求
|
||||||
|
while(1){
|
||||||
|
clnt_sock = accept(serv_sock, (struct sockaddr*)&clnt_addr, &clnt_addr_size);//接收客户端发来的请求
|
||||||
|
//单独创建一个线程,处理客户端的请求
|
||||||
|
if(clnt_sock >0){
|
||||||
|
pthread_t myThread;
|
||||||
|
int ret;
|
||||||
|
//threadFun() 为线程要执行的函数,clnt_sock 将作为实参传递给 threadFun() 函数
|
||||||
|
ret = pthread_create(&myThread, NULL, threadFun, &clnt_sock);
|
||||||
|
if (ret != 0) {
|
||||||
|
printf("线程创建失败\n");
|
||||||
|
exit(0);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void * threadFun(void * args) {
|
||||||
|
//将子线程和主线程脱离,子线程执行结束后自动释放资源
|
||||||
|
pthread_detach(pthread_self());
|
||||||
|
int clnt_sock = *(int*)args;
|
||||||
|
char buff[BUFFLEN]={0};
|
||||||
|
//获取http请求的字符串,num 为字符串的长度
|
||||||
|
int num = read(clnt_sock, buff, sizeof(buff));
|
||||||
|
if (num > 0) {
|
||||||
|
FILE * fp = NULL;
|
||||||
|
int nCount = 0;
|
||||||
|
int fp_has = 1,fp_type = 1;
|
||||||
|
int file_len, hdr_len;
|
||||||
|
char *type = NULL;
|
||||||
|
char http_header[BUFFLEN];
|
||||||
|
char file_name[HTTP_FILENAME_LEN] = { 0 }, suffix[16] = { 0 };
|
||||||
|
//获取目标文件(含路径)和后缀名
|
||||||
|
http_parse_request_cmd(buff, file_name, suffix);
|
||||||
|
//获取文件对应的 MIME 类型
|
||||||
|
type = http_get_type_by_suffix(suffix);
|
||||||
|
//如果类型未找到,则向客户端发送 errno.html 文件
|
||||||
|
if (type == NULL)
|
||||||
|
{
|
||||||
|
fp_type = 0;
|
||||||
|
printf("访问的文件类型(后缀名)不匹配\n");
|
||||||
|
type = http_get_type_by_suffix("html");
|
||||||
|
fp = fopen("errno.html","rb");
|
||||||
|
}else{
|
||||||
|
fp = fopen(file_name, "rb");
|
||||||
|
//如果服务器未找到目标文件,向客户端发送 errno.html 文件
|
||||||
|
if (fp == NULL) {
|
||||||
|
fp_has = 0;
|
||||||
|
fp = fopen("errno.html","rb");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//计算文件中包含的字节数
|
||||||
|
fseek(fp, 0, SEEK_END);
|
||||||
|
file_len = ftell(fp);
|
||||||
|
fseek(fp, 0, SEEK_SET);
|
||||||
|
//更新 http 响应的字符串
|
||||||
|
hdr_len = sprintf(http_header, http_res_hdr_tmpl, file_len, type);
|
||||||
|
//向客户端发送响应行、响应头和空行
|
||||||
|
write(clnt_sock, http_header, hdr_len);
|
||||||
|
|
||||||
|
if(fp_type == 1){
|
||||||
|
if (fp_has == 0) {
|
||||||
|
printf("服务器不存在 %s 文件\n", file_name);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
printf("服务器存在 %s 文件,发送中...\n",file_name);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
//向客户端发送文件内容,即响应体
|
||||||
|
memset(buff, 0, BUFFLEN);
|
||||||
|
while ((nCount = fread(buff, 1, BUFFLEN, fp)) > 0) {
|
||||||
|
write(clnt_sock, buff, nCount);
|
||||||
|
memset(buff, 0, BUFFLEN);
|
||||||
|
}
|
||||||
|
fclose(fp);
|
||||||
|
shutdown(clnt_sock, SHUT_WR);
|
||||||
|
read(clnt_sock, buff, sizeof(buff));
|
||||||
|
close(clnt_sock);
|
||||||
|
}
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *http_get_type_by_suffix(const char *suffix)
|
||||||
|
{
|
||||||
|
struct doc_type *type = NULL;
|
||||||
|
|
||||||
|
for (type = file_type; type->suffix; type++)
|
||||||
|
{
|
||||||
|
if (strcmp(type->suffix, suffix) == 0)
|
||||||
|
return type->type;
|
||||||
|
}
|
||||||
|
|
||||||
|
return NULL;
|
||||||
|
}
|
||||||
|
|
||||||
|
void http_parse_request_cmd(char *buf,char *file_name, char *suffix)
|
||||||
|
{
|
||||||
|
int file_length = 0, suffix_length = 0;
|
||||||
|
char *begin=NULL, *end=NULL, *bias=NULL;
|
||||||
|
|
||||||
|
//查找 URL 的开始位置
|
||||||
|
begin = strchr(buf, ' ');
|
||||||
|
begin += 1;
|
||||||
|
|
||||||
|
//查找 URL 的结束位置
|
||||||
|
end = strchr(begin, ' ');
|
||||||
|
*end = 0;
|
||||||
|
//得到要访问的目标文件(含路径)
|
||||||
|
file_length = end - begin - 1;
|
||||||
|
memcpy(file_name, begin+1, file_length);
|
||||||
|
file_name[file_length] = 0;
|
||||||
|
//获得文件的后缀名
|
||||||
|
bias = strrchr(begin, '/');
|
||||||
|
suffix_length = end - bias;
|
||||||
|
if (*bias == '/')
|
||||||
|
{
|
||||||
|
bias++;
|
||||||
|
suffix_length--;
|
||||||
|
}
|
||||||
|
if (suffix_length > 0)
|
||||||
|
{
|
||||||
|
begin = strchr(file_name, '.');
|
||||||
|
if (begin)
|
||||||
|
strcpy(suffix, begin + 1);
|
||||||
|
}
|
||||||
|
}
|
Binary file not shown.
Binary file not shown.
|
@ -0,0 +1,43 @@
|
||||||
|
// a->客户端
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int a_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (a_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器在本地
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
char buf[1] = "";
|
||||||
|
bzero(&buf, sizeof(buf));
|
||||||
|
scanf("%s", buf);
|
||||||
|
sendto(a_fd, buf, strlen(buf), 0, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
|
||||||
|
char recvbuf[128] = "";
|
||||||
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
recvfrom(a_fd, recvbuf, strlen(recvbuf), 0, (struct sockaddr *)&addr, &addr_len);
|
||||||
|
printf("%s", recvbuf);
|
||||||
|
|
||||||
|
if (strncmp(recvbuf, "bye", 3) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(a_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,42 @@
|
||||||
|
// a->客户端
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int a_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (a_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = inet_addr("127.0.0.1"); // 服务器在本地
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
int n = 0;
|
||||||
|
scanf("%d", &n);
|
||||||
|
sendto(a_fd, &n, sizeof(n), 0, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
|
||||||
|
char recvbuf[128] = "";
|
||||||
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
recvfrom(a_fd, recvbuf, strlen(recvbuf), 0, (struct sockaddr *)&addr, &addr_len);
|
||||||
|
printf("%s", recvbuf);
|
||||||
|
|
||||||
|
if (strncmp(recvbuf, "bye", 3) == 0)
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
close(a_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
|
@ -0,0 +1,54 @@
|
||||||
|
// b->服务端
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <string.h>
|
||||||
|
#include <arpa/inet.h>
|
||||||
|
#include <netinet/in.h>
|
||||||
|
#include <sys/socket.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
#include <stdlib.h>
|
||||||
|
|
||||||
|
int main(int argc, char const *argv[])
|
||||||
|
{
|
||||||
|
int b_fd = socket(AF_INET, SOCK_DGRAM, 0);
|
||||||
|
if (b_fd < 0)
|
||||||
|
{
|
||||||
|
perror("socket");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
struct sockaddr_in addr;
|
||||||
|
bzero(&addr, sizeof(addr));
|
||||||
|
addr.sin_family = AF_INET;
|
||||||
|
addr.sin_port = htons(8000);
|
||||||
|
addr.sin_addr.s_addr = htonl(INADDR_ANY); // 接收所有本地ip下同一网段的客户端消息
|
||||||
|
// addr.sin_addr.s_addr = inet_addr("127.0.0.1");
|
||||||
|
bind(b_fd, (struct sockaddr *)&addr, sizeof(addr));
|
||||||
|
|
||||||
|
while (1)
|
||||||
|
{
|
||||||
|
struct sockaddr_in src_addr;
|
||||||
|
bzero(&src_addr, sizeof(src_addr));
|
||||||
|
socklen_t src_addr_len = sizeof(src_addr);
|
||||||
|
int n;
|
||||||
|
socklen_t addr_len = sizeof(addr);
|
||||||
|
recvfrom(b_fd, &n, sizeof(n), 0, (struct sockaddr *)&src_addr, &src_addr_len);
|
||||||
|
printf("%d", n);
|
||||||
|
|
||||||
|
char sendbuf[128] = "";
|
||||||
|
|
||||||
|
if (n == 1)
|
||||||
|
strcpy(sendbuf, "disen666");
|
||||||
|
else if (n == 2)
|
||||||
|
strcpy(sendbuf, "jack good");
|
||||||
|
else if (n == 3)
|
||||||
|
strcpy(sendbuf, "disen888");
|
||||||
|
else if (n == 4)
|
||||||
|
strcpy(sendbuf, "bye");
|
||||||
|
|
||||||
|
sendto(b_fd, sendbuf, strlen(sendbuf), 0, (struct sockaddr *)&src_addr, src_addr_len);
|
||||||
|
}
|
||||||
|
|
||||||
|
close(b_fd);
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
Loading…
Reference in New Issue