计网项目二简单文件传输软件 socket接口部分

计网项目二简单文件传输软件 socket接口部分

简介

课程的团队项目,初学socket和单例模式,对socket的调用方式进行了封装(Windows系统下),
对于socket的具体函数的了解较少,故没有充足的注释

代码

服务端代码如下
Servre.h

#pragma once
#include <iostream>
#include <cstdlib>
#include <winsock2.h>  

#pragma comment(lib,"ws2_32.lib")  

namespace server
{
    class Serverh
    {

    private:
        WORD sockVersion;
        WSADATA wsaData;
        sockaddr_in sin;
        SOCKET slisten;
        SOCKET sClient;
        sockaddr_in remoteAddr;
        int nAddrlen;
        char revData[255];
        u_short ip;
        static Server* instance;

        Server();
        //Server(Server&) = delete;
        //Server& operator= (const Server&) = delete;

    public:
        
        /** 判断是否初始化成功 */
        bool isInit();

        /** 循环接收客户端信息 */
        void start();

        /** 修改ip */
        void setIp(u_short);

        /** 获取单例模式 */
        static Server* getInstance();

    };

}

Server.cpp

#include "Server.h"
using namespace server;

Server* Server::instance = NULL;

Server::Server()
{
	ip = 8888;
	sockVersion = MAKEWORD(2, 2);
	//slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	sin.sin_family = AF_INET;
	sin.sin_port = htons(ip);
	sin.sin_addr.S_un.S_addr = INADDR_ANY;
	nAddrlen = sizeof(remoteAddr);

}

void server::Server::setIp(u_short IP)
{
	this->ip = IP;
}

Server* server::Server::getInstance()
{
	if (Server::instance == NULL)
		instance = new Server;
	return instance;
}

bool server::Server::isInit()
{
	if (WSAStartup(sockVersion, &wsaData) != 0)
	{
		return false;
	}
	slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
	if (slisten == INVALID_SOCKET)
	{
		printf("socket error !");
		return false;
	}

	if (bind(slisten, (LPSOCKADDR)&sin, sizeof(sin)) == SOCKET_ERROR)
	{
		printf("bind error !");
		return false;
	}

	if (listen(slisten, 5) == SOCKET_ERROR)
	{
		printf("listen error !");
		return false;
	}

	return true;
}

void server::Server::start()
{
	if (!isInit())
		return;


	while (true)
	{
		printf("等待连接...\n");
		sClient = accept(slisten, (SOCKADDR*)&remoteAddr, &nAddrlen);
		if (sClient == INVALID_SOCKET)
		{
			printf("accept error !");
			continue;
		}
		printf("接受到一个连接:%s \r\n", inet_ntoa(remoteAddr.sin_addr));

		//接收数据  
		int ret = recv(sClient, revData, 255, 0);
		if (ret > 0)
		{
			revData[ret] = 0x00;
			printf(revData);
			printf("\n");
		}

		//发送数据  
		const char* sendData = "你好,TCP客户端!\n";
		send(sClient, sendData, strlen(sendData), 0);
		closesocket(sClient);
	}

	closesocket(slisten);
	WSACleanup();

	return;
}

客户端代码如下:
Cilent.h

#pragma once
#include<WINSOCK2.H>
#include<stdio.h>
#include<iostream>
#include<cstring>

#pragma comment(lib, "ws2_32.lib")

namespace cilent
{
	class Cilent
	{
	public:
		/** 获取单例模式实例 */
		static Cilent* getInstance();
		/** 运行入口 */
		void start();



	private:
		WORD sockVersion;
		WSADATA wasdata;
		sockaddr_in serAddr;
		SOCKET sclient;
		std::string data;
		const char* sendData;
		char revData[255];
		u_short ip;

		static Cilent* instance;

		Cilent();
	};
}

Cilent.cpp

#include "Cilent.h"
using namespace cilent;

Cilent* Cilent::instance = NULL;

Cilent::Cilent()
{
	sockVersion = MAKEWORD(2, 2);
	serAddr.sin_family = AF_INET;
	serAddr.sin_port = htons(8888);
	serAddr.sin_addr.S_un.S_addr = inet_addr("106.52.165.96");
}

Cilent* Cilent::getInstance()
{
	if (instance == NULL)
		instance = new Cilent;
	return instance;
}

void Cilent::start()
{
	if (WSAStartup(sockVersion, &wasdata) != 0)
	{
		std::cout << "初始化失败" << std::endl;
		return;
	}

	while (true) {
		sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
		if (sclient == INVALID_SOCKET)
		{
			printf("invalid socket!");
			return;
		}

		if (connect(sclient, (sockaddr*)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
		{  //连接失败 
			printf("connect error !");
			closesocket(sclient);
			return;
		}

		std::cin >> data;
		sendData = data.c_str();   //string转const char* 
		//char * sendData = "你好,TCP服务端,我是客户端\n";
		send(sclient, sendData, strlen(sendData), 0);
		//send()用来将数据由指定的socket传给对方主机
		//int send(int s, const void * msg, int len, unsigned int flags)
		//s为已建立好连接的socket,msg指向数据内容,len则为数据长度,参数flags一般设0
		//成功则返回实际传送出去的字符数,失败返回-1,错误原因存于error 

		char recData[255];
		int ret = recv(sclient, recData, 255, 0);
		if (ret > 0) {
			recData[ret] = 0x00;
			printf(recData);
		}
		closesocket(sclient);
	}
}

总结

在修改成单例模式时遇到了个bug,如果
sClient = accept(slisten, (SOCKADDR*)&remoteAddr, &nAddrlen);
不在Start里调用,则会出现socket error.
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值