浏览代码

Merge branch 'master' of gitlab.ethz.ch:mawinkle/socket

mawinkle 6 年之前
父节点
当前提交
be559e935e
共有 4 个文件被更改,包括 232 次插入5 次删除
  1. 1 0
      .gitignore
  2. 25 2
      socketio.hpp
  3. 204 0
      socketio_win32.cpp
  4. 2 3
      test.cpp

+ 1 - 0
.gitignore

@@ -4,3 +4,4 @@
 *.lib
 *.so
 s
+*.exe

+ 25 - 2
socketio.hpp

@@ -1,3 +1,5 @@
+#ifndef SOCKETIO_HPP
+#define SOCKETIO_HPP
 #include <string>
 #include <cstring>
 #include <vector>
@@ -5,17 +7,32 @@
 #include <exception>
 #include <cmath>
 #include <stdexcept>
-
+#ifndef _WIN32
 #include <sys/socket.h>
 #include <netinet/in.h>
+#else
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#pragma comment(lib, "ws2_32.lib")
+#endif
 class cppsocket{
 private:
+#ifdef _WIN32
+	WSADATA wsa;
+	SOCKET s;
+	std::vector<char> buffer;
+#else
 	struct sockaddr_in serv_addr;
 	int sock;
 	std::vector<char> buffer;
+#endif
 public:
 	const static std::size_t buffersize = 256;
+#ifdef _WIN32
+	cppsocket(WSADATA d, SOCKET _s);
+#else
 	cppsocket(sockaddr_in _serv_addr, int _sock);
+#endif
 	cppsocket();
 	cppsocket(const std::string& addr, unsigned int PORT);
 	void close();
@@ -27,17 +44,23 @@ public:
 
 class server_socket{
 private:
+#ifdef _WIN32
+	WSADATA wsaData;
+	int iResult;
+	SOCKET ListenSocket = INVALID_SOCKET;
+#else
 	int port_;
 	int server_fd;
 	struct sockaddr_in address;
 	socklen_t addrlen;
+#endif
 public:
 	int port();
 	server_socket(int _port);
 	cppsocket accept_connection();
 	void close();
 };
-
+#endif
 
 
 

+ 204 - 0
socketio_win32.cpp

@@ -0,0 +1,204 @@
+#include "socketio.hpp"
+#include <stdio.h>
+#include <winsock2.h>
+#include <ws2tcpip.h>
+#pragma comment(lib, "ws2_32.lib")
+#include <string>
+#include <cstring>
+#include <vector>
+#include <iostream>
+
+using std::size_t;
+struct socket_exception : public std::exception{
+	std::string msg;
+	socket_exception(std::string&& _msg){
+		msg = std::move(_msg);
+	}
+	socket_exception(const std::string& _msg){
+		msg = _msg;
+	}
+	socket_exception(const char* _msg){
+		msg = std::string(_msg);
+	}
+	const char* what() const throw (){
+		//return "asdasdsa";
+    	return msg.length() == 0 ? "Connection creation failure" : msg.c_str();
+    }
+};
+
+std::string GetLastErrorAsString(){
+    //Get the error message, if any.
+    DWORD errorMessageID = ::GetLastError();
+    if(errorMessageID == 0)
+        return std::string();
+
+    LPSTR messageBuffer = nullptr;
+    size_t size = FormatMessageA(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM | FORMAT_MESSAGE_IGNORE_INSERTS,
+                                 NULL, errorMessageID, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), (LPSTR)&messageBuffer, 0, NULL);
+
+    std::string message(messageBuffer, size);
+
+    //Free the buffer.
+    LocalFree(messageBuffer);
+
+    return message;
+}
+
+cppsocket::cppsocket(){}
+cppsocket::cppsocket(WSADATA d, SOCKET _s){
+	s = _s;
+	wsa = d;
+	buffer = std::vector<char>(buffersize);
+}
+cppsocket::cppsocket(const std::string& addr, unsigned int PORT){
+	struct sockaddr_in server;
+	buffer = std::vector<char>(buffersize);
+	int recv_size;
+	
+	if (WSAStartup(MAKEWORD(2,2),&wsa) != 0){
+		throw socket_exception(std::string("Socket creation error: ") + GetLastErrorAsString());
+	}
+	
+	if((s = socket(AF_INET , SOCK_STREAM , 0 )) == INVALID_SOCKET){
+		throw socket_exception(std::string("Socket creation error: ") + GetLastErrorAsString());
+	}
+	
+	server.sin_addr.s_addr = inet_addr(addr.c_str());
+	server.sin_family = AF_INET;
+	server.sin_port = htons(PORT);
+
+	if (connect(s , (struct sockaddr *)&server , sizeof(server)) < 0){
+		throw socket_exception(std::string("Could not connect to host: ") + GetLastErrorAsString());
+	}
+}
+void cppsocket::write(const std::string& message){
+	std::vector<char> msg(message.c_str(), message.c_str() + message.size());
+	write(msg);
+}
+void cppsocket::write(const std::vector<char>& message){
+	for(size_t i = 0;i < message.size();i += buffersize){
+		char cs[buffersize + 1] = {0};
+		std::memcpy(cs, message.data() + i,buffersize);
+		if((i + buffersize) < message.size()){
+			cs[buffersize] = 'c';
+			if(send(s, cs, buffersize + 1, 0) < 0){
+				throw socket_exception(std::string("Couldn't write to peer: ") + GetLastErrorAsString());
+			}
+		}
+		else{
+			cs[message.size() - i] = (char)0;
+			if(send(s, cs, message.size() - i, 0) < 0){
+				throw socket_exception(std::string("Couldn't write to peer: ") + GetLastErrorAsString());
+			}
+		}
+	}
+}
+std::vector<char> cppsocket::receive(){
+	std::vector<char> stor;
+	while(true){
+		std::fill(buffer.begin(), buffer.end(), (char)0);
+		ssize_t val = recv(s, buffer.data(), buffersize + 1,0);
+		if(val == 0)throw socket_exception("Connection closed by peer");
+		if(val < 0){
+			throw socket_exception(GetLastErrorAsString());
+		}
+		stor.insert(stor.end(), buffer.begin(), buffer.begin() + std::min(val, (ssize_t)buffersize));
+		if(buffer.data()[buffersize] == (char)0){break;}
+	}
+	std::cout << std::endl;
+	return stor;
+}
+void cppsocket::close(){
+	closesocket(s);
+}
+
+server_socket::server_socket(int port){
+	struct addrinfo *result = NULL;
+	struct addrinfo hints;
+	iResult = WSAStartup(MAKEWORD(2,2), &wsaData);
+	if (iResult != 0) {
+		printf("WSAStartup failed with error: %d\n", iResult);
+	}
+	ZeroMemory(&hints, sizeof(hints));
+	hints.ai_family = AF_INET;
+	hints.ai_socktype = SOCK_STREAM;
+	hints.ai_protocol = IPPROTO_TCP;
+	hints.ai_flags = AI_PASSIVE;
+
+	// Resolve the server address and port
+	iResult = getaddrinfo(NULL, std::to_string(port).c_str(), &hints, &result);
+	if ( iResult != 0 ) {
+		printf("getaddrinfo failed with error: %d\n", iResult);
+		WSACleanup();
+	}
+
+	// Create a SOCKET for connecting to server
+	ListenSocket = socket(result->ai_family, result->ai_socktype, result->ai_protocol);
+	if (ListenSocket == INVALID_SOCKET) {
+		printf("socket failed with error: %ld\n", WSAGetLastError());
+		freeaddrinfo(result);
+		WSACleanup();
+	}
+
+	// Setup the TCP listening socket
+	iResult = bind( ListenSocket, result->ai_addr, (int)result->ai_addrlen);
+	if (iResult == SOCKET_ERROR) {
+		printf("bind failed with error: %d\n", WSAGetLastError());
+		freeaddrinfo(result);
+		closesocket(ListenSocket);
+		WSACleanup();
+	}
+	freeaddrinfo(result);
+	iResult = listen(ListenSocket, SOMAXCONN);
+	if (iResult == SOCKET_ERROR) {
+		printf("listen failed with error: %d\n", WSAGetLastError());
+		closesocket(ListenSocket);
+		WSACleanup();
+	}
+}
+cppsocket server_socket::accept_connection(){
+	SOCKET ClientSocket = accept(ListenSocket, NULL, NULL);
+	if (ClientSocket == INVALID_SOCKET) {
+		printf("accept failed with error: %d\n", WSAGetLastError());
+		closesocket(ListenSocket);
+		WSACleanup();
+	}
+	return cppsocket(wsaData, ClientSocket);
+}
+void server_socket::close(){
+	closesocket(ListenSocket);
+}
+/*int main(int argc, char** argv){
+	server_socket ssock(80);
+	while(true){
+		cppsocket sock = ssock.accept_connection();
+		sock.write("ab");
+		std::vector<char> rec = sock.receive();
+		std::cout << rec << ", ";
+		std::cout << rec << std::endl;
+		sock.close();
+	}
+	ssock.close();
+	
+	//Send some data
+	std::string _message = std::string("Hallo");
+	memcpy(message, _message.c_str(), _message.length() + 1);
+	if( send(s , message , strlen(message) , 0) < 0){
+		puts("Send failed");
+		return 1;
+	}
+	puts("Data Send\n");
+	
+	//Receive a reply from the server
+	if((recv_size = recv(s , server_reply , 2000 , 0)) == SOCKET_ERROR){
+		puts("recv failed");
+	}
+	
+	puts("Reply received\n");
+	
+	//Add a NULL terminating character to make it a proper string before printing
+	server_reply[recv_size] = '\0';
+	puts(server_reply);
+	
+	return 0;
+}*/

+ 2 - 3
test.cpp

@@ -1,6 +1,5 @@
 #include "socketio.hpp"
 #include <iostream>
-#include <thread>
 #include <chrono>
 template<typename T>
 std::ostream& operator<<(std::ostream& out, std::vector<T> o){
@@ -21,8 +20,8 @@ std::ostream& operator<< <char>(std::ostream& out, std::vector<char> o){
 	return out;
 }
 int main(){
-	//cppsocket sock("192.168.178.79", 80);
-	cppsocket sock("127.0.0.1", 80);
+	cppsocket sock("192.168.178.79", 80);
+	//cppsocket sock("127.0.0.1", 80);
 	std::vector<char> toSend(10000);
 	for(unsigned int i = 0;i < toSend.size();i++){
 		toSend[i] = (char)(i * i) % 10 + 'a';