未经检验过
转自:http://www.iteye.com/topic/368949
#include <winsock.h>
#include <sys/stat.h>
#include <iostream>
using namespace std;
#define SERVER_PORT 10000 //自定义的服务端口
#define HOSTLEN 256 //主机名长度
#define BACKLOG 10 //同时等待的连接个数
int sendall(int s, char *buf, int *len) {
int total = 0; // 已经发送字节数
int bytesleft = *len; //还剩余多少字节
int n;
while(total < *len) {
n = send(s, buf+total, bytesleft, 0);
if (n == -1) { break; }
total += n;
bytesleft -= n;
}
*len = total; // 返回实际发送出去的字节数
return n==-1?-1:0; // 成功发送返回0 失败-1
}
void wrong_req(int sock) {
char* error_head = "HTTP/1.0 501 Not Implemented\r\n"; //输出501错误
int len = strlen(error_head);
if (sendall(sock, error_head, &len) == -1) { //向客户发送
printf("Sending failed!");
return;
}
char* error_type = "Content-type: text/plain\r\n";
len = strlen(error_type);
if (sendall(sock, error_type, &len) == -1) {
printf("Sending failed!");
return;
}
char* error_end = "\r\n";
len = strlen(error_end);
if (sendall(sock, error_end, &len) == -1) {
printf("Sending failed!");
return;
}
char* prompt_info = "The command is not yet completed\r\n";
len = strlen(prompt_info);
if (sendall(sock, prompt_info, &len) == -1) {
printf("Sending failed!");
return;
}
}
bool not_exit(char* arguments) {
struct stat dir_info;
return (stat(arguments, &dir_info) == -1);
}
void file_not_found(char* arguments, int sock) {
char* error_head = "HTTP/1.0 404 Not Found\r\n"; //构造404错误head
int len = strlen(error_head);
if (sendall(sock, error_head, &len) == -1) { //向客户端发送
printf("Sending error!");
return;
}
char* error_type = "Content-type: text/plain\r\n";
len = strlen(error_type);
if (sendall(sock, error_type, &len) == -1) {
printf("Sending error!");
return;
}
char* error_end = "\r\n";
len = strlen(error_end);
if (sendall(sock, error_end, &len) == -1) {
printf("Sending error!");
return;
}
char prompt_info[50] = "Not found: ";
strcat(prompt_info, arguments);
len = strlen(prompt_info);
if (sendall(sock, prompt_info, &len) == -1) { //输出未找到的文件
printf("Sending error!");
return;
}
}
void send_header(int send_to, char* content_type) {
char* head = "HTTP/1.0 200 OK\r\n"; //正确的头部信息
int len = strlen(head);
if (sendall(send_to, head, &len) == -1) { //向连接的客户端发送数据
printf("Sending error");
return;
}
if (content_type) { //content_type不为空
char temp_1[30] = "Content-type: "; //准备好要连接的字串
strcat(temp_1, content_type); //构造content_type
strcat(temp_1, "\r\n");
len = strlen(temp_1);
if (sendall(send_to, temp_1, &len) == -1) {
printf("Sending error!");
return;
}
}
}
char* file_type(char* arg) {
char * temp; //临时字符串指针
if ((temp=strrchr(arg,'.')) != NULL) { //取得后缀
return temp+1;
}
return ""; //如果请求的文件名中没有. 则返回空串
}
void send_file(char* arguments, int sock) {
char* extension = file_type(arguments); //获得文件后缀名
char* content_type = "text/plain"; //初始化type='text/plain'
FILE* read_from; //本地文件指针从该文件中读取.html .jpg等
int readed = -1; //每次读得的字节数
if (strcmp(extension, "html") == 0) { //发送内容为html
content_type = "text/html";
}
if (strcmp(extension, "gif") == 0) { //发送内容为gif
content_type = "image/gif";
}
if (strcmp(extension, "jpg") == 0) { //发送内容为jpg
content_type = "image/jpg";
}
read_from = fopen(arguments, "r"); //打开用户指定的文件准备读取
if(read_from != NULL) { //指针不为空
char read_buf[128]; //读文件时的字节缓存数组
send_header(sock, content_type); //发送协议头
send(sock, "\r\n", 2, 0); //再加一个"\r\n" 不能缺少 格式要求
while(!feof(read_from)) { //判断文件是否已经结束
fgets(read_buf, 128, read_from); //读取
int len = strlen(read_buf);
if (sendall(sock, read_buf, &len) == -1) { //发送数据
printf("Sending error!"); //出现发送错误显示到控制台继续发送
continue;
}
}
}
}
void handle_req(char* request, int client_sock) {
char command[BUFSIZ]; //保存解析到的命令字段 GET PUT
char arguments[BUFSIZ]; //保存解析到的请求的文件
strcpy(arguments, "./"); //注意该符号在不同操作系统的区别
if (sscanf(request, "%s%s", command, arguments+2) != 2) {
return; //解析出错在返回
}
printf("handle_cmd: %s\n",command); //向控制台输出此时的命令
printf("handle_path: %s\n",arguments); //向控制台输出此时的请求路径
if (strcmp(command, "GET") != 0) { //请求命令格式是否正确
wrong_req(client_sock);
return;
}
if (not_exit(arguments)) { //请求的文件是否存在
file_not_found(arguments, client_sock);
return;
}
send_file(arguments, client_sock); //命令格式及请求路径正确则发送数据
return;
}
int make_server_socket() {
struct sockaddr_in server_addr; //服务器地址结构体
int tempSockId; //临时存储socket描述符
tempSockId = socket(PF_INET, SOCK_STREAM, 0);
if (tempSockId == -1) { //如果返回值为-1 则出错
return -1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = inet_addr("127.0.0.1"); //本地地址
memset(&(server_addr.sin_zero), '\0', 8);
if (bind(tempSockId, (struct sockaddr *)&server_addr,
sizeof(server_addr)) == -1) { //绑定服务如果出错则返回-1
printf("bind error!\n");
return -1;
}
if (listen(tempSockId, BACKLOG) == -1 ) { //开始监听
printf("listen error!\n");
return -1;
}
return tempSockId; //返回取得的SOCKET
}
void main(int argc, char * argv[]) {
WSADATA wsaData;
if (WSAStartup(MAKEWORD(1, 1), &wsaData) != 0) {
fprintf(stderr, "WSAStartup failed.\n");
exit(1);
}
printf("My web server started...\n");
int server_socket; //服务器的socket
int acc_socket; //接收到的用户连接的socket
int sock_size = sizeof(struct sockaddr_in);
struct sockaddr_in user_socket; //客户连接信息
server_socket = make_server_socket(); //创建服务器端的socket
if (server_socket == -1) { //创建socket出错
printf("Server exception!\n");
exit(2);
}
while(true) {
acc_socket = accept(server_socket, (struct sockaddr *)&user_socket, &sock_size); //接收连接
//cout << inet_ntoa(user_socket.sin_addr) << endl; //测试用:-)//
int numbytes;
char buf[100];
if ((numbytes=recv(acc_socket, buf, 99, 0)) == -1) {
perror("recv");
exit(1);
}
//printf("buf ... %s", buf); //测试用
handle_req(buf, acc_socket);
}
}
分享到:
相关推荐
本篇文章将深入探讨Objective-C如何实现Socket编程,并结合iPhone和Mac平台的示例进行详细讲解。 首先,Socket是网络编程中的一个接口,它提供了一种在不同计算机之间建立连接并交换数据的方式。在Objective-C中,...
通过阅读和分析这些代码,可以更好地理解C语言实现socket通信的细节。为了更深入地学习,你可以尝试修改代码,添加新的功能,例如添加SSL/TLS加密以实现安全的TCP通信,或者实现UDP协议的socket通信。实践是检验理解...
在IT行业中,网络通信是计算机科学的一个重要领域,而Socket编程是实现网络通信的基础。本教程将深入探讨如何使用C语言实现基于Socket的客户端-服务器通信。在完成这个项目后,用户可以通过telnet连接到localhost并...
在IT行业中,网络编程是不可或缺的一部分,而Socket编程则是实现网络通信的基础。本文将深入探讨如何利用多线程和Socket技术来实现一个简单的群聊应用。这个应用包括两个主要部分:服务端(Server)和客户端(Client...
在C语言中,我们通常使用伯克利套接字(BSD Socket)API来实现Socket编程。该API源于BSD操作系统,现在广泛应用于各种操作系统,包括Linux和Windows。 创建Socket首先需要调用`socket()`函数,它返回一个描述符,...
本篇将详细探讨如何使用C语言实现socket服务端和客户端。 首先,我们要了解socket是什么。Socket是网络通信的一种接口,它允许两台计算机通过网络进行数据交换。在C语言中,我们通常使用套接字库(通常为`<sys/...
在实现Socket聊天程序时,我们需要关注以下几个关键步骤: 1. **创建Socket**:首先,我们需要调用`socket()`函数创建一个Socket。该函数会返回一个描述符,用于后续的所有Socket操作。例如: ```c++ int socket_...
本主题将深入探讨如何使用C语言实现TCP的Socket编程,包括客户端和服务端的构建。TCP是一种面向连接的、可靠的传输协议,而Socket则是操作系统提供给应用程序用于网络通信的接口。 首先,我们需要理解TCP Socket...
在这个"标准C实现的Socket服务端和客户端源码"中,我们可以深入学习和理解如何在C语言环境下编写Socket程序。以下是对相关知识点的详细说明: 1. **Socket基础知识**: Socket是一种在不同或相同计算机之间进行...
"使用C_C++实现Socket聊天程序" 该资源主要讲解了使用C/C++实现Socket聊天程序的相关知识点。下面是相关知识点的详细说明: 1. Socket编程基础 Socket编程是网络编程的基础,Socket是操作系统提供的一种机制,...
本文将深入探讨如何使用C/C++编程语言,通过TCP/IP协议来构建一个支持多人聊天的服务器和客户端系统。 首先,TCP/IP(Transmission Control Protocol/Internet Protocol)是互联网上广泛采用的一组通信协议,它为...
"C++线程池结合IOCP完成端口实现socket高并发服务端程序"是一个利用现代C++特性,结合IO Completion Ports(IOCP)技术以及线程池策略来优化socket服务器性能的项目。IOCP是Windows操作系统中一种高效的I/O模型,...
### Socket接口原理及C语言实现 #### 一、Socket接口基础概念 Socket是网络通信的基础,它提供了一种进程间...无论是C语言还是其他编程语言,Socket的核心思想和实现步骤都相似,主要区别在于语法和库函数的不同。
本教程将详细解释如何在Android中实现Java和C的Socket通信,特别是在涉及文件描述符传递的场景下。 1. **Java Socket基础** Java中的`java.net.Socket`类提供了网络通信的能力,它允许我们在两个应用程序之间建立...
在这个项目中,我们关注的是“标准C实现的Socket服务端源码”的makefile部分,这对于理解整个项目的构建流程至关重要。makefile是Unix/Linux环境下的一种自动化编译工具,它能够根据依赖关系自动编译和链接源代码,...
我们的实验报告,C实现FTP客户端,有实验... socket编程实例C实现FTP客户端 socket编程实例C实现FTP客户端 socket编程实例C实现FTP客户端 socket编程实例C实现FTP客户端 socket编程实例C实现FTP客户端 socket编程实例
最后,压缩包中的文件"ping"可能是实现这个功能的源代码文件,可能包含了C、C++或其他编程语言的实现。通过阅读和分析这个文件,你可以看到如何在实际代码中设置Socket选项,打开SOCK_RAW套接字,构造和发送ICMP报文...
C语言中的Socket编程主要依赖于`socket()`、`bind()`、`listen()`、`accept()`等函数来实现服务器端与客户端之间的通信。 - **创建Socket**:通过调用`socket()`函数创建一个Socket,该函数需要三个参数:协议族、...
在本文中,我们将深入探讨如何在Win32平台上利用C++和Socket技术构建一个C/S架构的聊天应用程序,实现客户端间的群聊和私聊功能。首先,我们需要了解几个关键概念和关键技术。 1. **Win32 API**:Windows操作系统...
以上就是C/C++实现Socket聊天程序的基本过程和相关知识点。在实际项目中,还需要考虑更多细节,例如错误处理、资源管理、安全性以及性能优化等。通过理解并实践这些基本概念,可以为更复杂的网络应用打下坚实的基础...