网络编程:服务端

一、单个sokect监听

#ifdef WIN32
//#include <windows.h>
#include<ws2tcpip.h>
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#unclude <stdlib.h>
#include <sys/socket.h> 
#incklude <
#define  closesocket close
#endif
#include <stdio.h>
#include<string>
	int main(int argc, char* argv[])
{
#ifdef WIN32
	WSADATA ws;
	WSAStartup(MAKEWORD(2, 2), &ws);
#endif
	for (int i = 0; i < 1; i++)
	{
		int sock = socket(AF_INET, SOCK_STREAM, 0);
		if (sock == -1)
		{
			printf("create socket failed!\n");
			return -1;
		}

		unsigned int port = 8080;

		if (argc > 1) {
			port = atoi(argv[1]);
		}

		sockaddr_in saddr;
		saddr.sin_family = AF_INET;   //协议
		saddr.sin_port = htons(port);   //端口号
		saddr.sin_addr.s_addr = htonl(0);  //ip地址

		if (bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0) {
			printf("bind port %d failed!\n", port);
			return -2;
		}
		printf("bind port %d success!\n", port);

		listen(sock, 10); //第二个参数表示缓冲区大小,即等待连接队列的最大长度  成功返回0,失败返回-1

		sockaddr_in caddr;
		socklen_t len = 0;

		int client = accept(sock, (sockaddr*)&caddr, &len);  //成功会返回一个新的sockt,失败返回-1
		printf("accept client %d\n", client);
		char* ip = inet_ntoa(caddr.sin_addr);    //获取ip号
		unsigned short cport = ntohs(caddr.sin_port); //获取端口号
		printf("client ip id %s,port is %d\n", cport, ip);

		/*函数原型:int accept( int fd, struct socketaddr* addr, socklen_t* len);
		* 功能:获取请求连接,返回新的套接字描述符
			 参数说明:
			 fd:套接字描述符。
			 addr:返回连接着的地址
			 len:接收返回地址的缓冲区长度 */

		char buf[1024] = { 0 };
		for (;;) {
			int recvlen = recv(client, buf, sizeof(buf) - 1, 0);
			/*
		* 函数原型:int recv(socket s, char FAR* buf, int len, int flags);
			函数说明:recv()用来接收指定的socket传来的数据,并把数据传到由参数buf指向的内存空间。
			参数说明:
			socket:一个标识已连接套接口的描述字。
			buf:用于接收数据的缓冲区。
			len:缓冲区长度。
			flags:指定调用方式。取值:MSG_PEEK 查看当前数据,数据将被复制到缓冲区中,但并不从输入队列中删除;MSG_OOB 处理带外数据。
			返回值:若无错误发生,recv()返回读入的字节数。如果连接已中止,返回0。否则的话,返回SOCKET_ERROR错误,
			应用程序可通过WSAGetLastError()获取相应错误代码。
		*/
			if (recvlen <= 0) break;
			buf[recvlen] = '\0';  //在字符串结尾加\0
			if (strstr(buf, "quit") != NULL) {  //接收到quit退出
				char re[] = "quit success!\n";
				send(client, re, strlen(re) + 1, 0);
				break;
				/*
				函数原型:
					int send( socket s, const char FAR* buf, int len, int flags);
					函数说明:向一个已连接的套接口发送数据。
					参数说明:
						s:一个用于标识已连接套接口的描述字。
						buf:包含待发送数据的缓冲区。
						len:缓冲区中数据的长度。
						flags:调用执行方式。
						返回值:如果成功,则返回发送的字节数,失败则返回SOCKET_ERROR。
				*/
			}
			int sendlen = send(client, "OK", 3, 0); //接收到数据返回ok
			printf("recv %s\n", buf);
		}





		closesocket(client);
		printf("[%d]", sock);
		//closesocket(sock);
	}
	getchar();
	return 0;
}

二、封装成类
1.Xtcp.h

#include<string>

class Xtcp
{
public:
	Xtcp();
	virtual ~Xtcp();

	int CreatSocket();
	bool Bind(unsigned short port);
	Xtcp Accept();
	void Close();
	int Recv(char* buf, int bufsize);
	int Send(const char* buf, int sendsize);

public:
	int sock = -1;
	unsigned short port = 0;
	std::string ip;


};

2.Xtcp.cpp

#include "Xtcp.h"
#include <string.h>
#include <stdio.h>
#include <stdlib.h>
#ifdef WIN32
#include <windows.h>
#define socklen_t int
#else
#include <sys/types.h>
#include <sys/socket.h>
#include <unistd.h>
#include <arpa/inet.h>
#define  closesocket close
#endif

#include<thread>
using namespace std;
Xtcp::Xtcp()
{
#ifdef WIN32
	static bool first = true;
	if (first)
	{
		first = false;
		WSADATA ws;
		WSAStartup(MAKEWORD(2, 2), &ws);
	}
#endif
}

int Xtcp::CreatSocket() {
	sock = socket(AF_INET, SOCK_STREAM, 0);
	if (sock == -1)
	{
		printf("create socket failed!\n");
		return -1;
	}
	printf("sock num: %d creat success!\n", sock);
	return sock;
}

bool Xtcp::Bind(unsigned short port)
{
	if (sock < 0)
		CreatSocket();
	sockaddr_in  saddr;
	saddr.sin_family = AF_INET;
	saddr.sin_port = htons(port);
	saddr.sin_addr.s_addr = htonl(0);
	if (::bind(sock, (sockaddr*)&saddr, sizeof(saddr)) != 0)
	{
		printf("bind port %d failed!\n", port);
		return false;
	}
	printf("bind port %d success!\n", port);
	listen(sock, 10);
	return true;
}

Xtcp Xtcp::Accept() {
	Xtcp tcp;
	sockaddr_in caddr;
	socklen_t len = sizeof(caddr);

	int client = accept(sock, (sockaddr*)&caddr, &len);  //成功会返回一个新的sockt,失败返回-1
	if (client <= 0) return tcp;
	printf("accept client %d\n", client);
	tcp.ip = inet_ntoa(caddr.sin_addr);    //获取ip号
	tcp.port = ntohs(caddr.sin_port); //获取端口号
	printf("client ip id %s,port is %d\n", tcp.ip.c_str(), tcp.port);
}

void Xtcp::Close() {
	if (sock < 0) return;
	closesocket(sock);
}

int Xtcp::Recv(char* buf, int bufsize) {
	return recv(sock, buf, bufsize, 0);
}
int Xtcp::Send(const char* buf, int sendsize) {
	int sendedsize = 0; //已发送长度
	while (sendedsize != sendedsize) {   //没有发送完毕就会一直发
		int len = send(sock, buf + sendedsize, sendsize - sendedsize, 0);
		if (len <= 0) break;
		sendedsize += len;
	}
	return sendedsize;
}

Xtcp::~Xtcp() {
}

3.main.cpp

#include<stdlib.h>
#include"Xtcp.h"
#include<thread>     //c++11中的线程库
#include <string.h>
class TcpThread {
public:
	void MainFunc() {
		char buf[1024] = { 0 };
		for (;;) {
			int recvlen = client.Recv(buf, sizeof(buf) - 1);
			if (recvlen <= 0) break;
			buf[recvlen] = '\0';  //在字符串结尾加\0
			if (strstr(buf, "quit") != NULL) {  //接收到quit退出
				char re[] = "quit success!\n";
				client.Send(re, strlen(re) + 1);
				break;
			}
			int sendlen = client.Send("OK", 4); //接收到数据返回ok
			printf("recv %s\n", buf);
		}
		client.Close();
		delete this;
	}
	Xtcp client;
};
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值