c++ winsocket (七)

一 问题 

  1  打开一个客户端不停地发包,资源监视器的网络IO 显示 1M/s的流量,再打开一个客户端,还是1M/s的流量,而且其中一个客户端会停止发包,过一会又会发包。

      回答: 因为 winsocket默认是阻塞的,accept() ,receive是阻塞函数,当receive没有收到 数据时,程序不会继续往下执行,当socket缓冲区的数据满了,会阻止客户端发送数据 ,会出现粘包。流量1M/s 是因为ui线程打印会消耗CPU。导致不能全力发送数据。

 

1 mysocket.h


const size_t IP_BUF_SIZE = 65;
#include "mythread.h"
class MySocket : public MyThread{
public:
 SOCKET	m_socket;
 SOCKET	m_con;
public:
	MySocket();
	~MySocket();
	void init();
	void mybind();
	void mylisten();
	SOCKET myaccept(); 
	void mysend(char * ch);
	void myrecv();
	void myclose();
	void run();
	void myconnect();
	

};

2 mythread.h


const size_t IP_BUF_SIZE = 65;
#include "mythread.h"
class MySocket : public MyThread{
public:
 SOCKET	m_socket;
 SOCKET	m_con;
public:
	MySocket();
	~MySocket();
	void init();
	void mybind();
	void mylisten();
	SOCKET myaccept(); 
	void mysend(char * ch);
	void myrecv();
	void myclose();
	void run();
	void myconnect();
	

};

3  client.cpp

#include <windows.h>
#include <iostream>
#include "mysocket.h"
enum CMD{
  CMD_LOGIN,
  CMD_LOGOUT
} ;
struct HeaderData{
	int datalegth;
	int cmd;
	 
  
 
};
struct LoginData{
  HeaderData headerdata;
  char username[100];
  int password;
};
void main(){
	    LoginData  logindata;
		logindata.headerdata.datalegth =104;
		logindata.headerdata.cmd = CMD_LOGIN;
	MySocket * mysocket= new MySocket();
	mysocket->init();
	mysocket->myconnect();
	int i =0;
		//std::cout<<"请输入"<<std::endl;
	while(1){
		//printf("请输入用户名");
		//scanf("%s",logindata.username);
		//printf("请输入密码");
		//scanf("%s",logindata.password);
	

		strcpy(logindata.username,"xiongwei");
		logindata.password = i;
			printf("已输入用户名:%s  密码:%d",logindata.username,logindata.password);
		//mysocket->mysend((char *)&logindata);
		i=i+1;
	   // Sleep(5000);//每5秒
	}
	
	system("pause");
	
}

4  mymain.cpp

#include <windows.h>
#include <process.h> 
#include "mysocket.h"
void receive(void * socket){
  MySocket  * mysocket ;
  mysocket =(MySocket *)socket;
  mysocket->myrecv();
}
void main321(){
	MySocket * mysocket= new MySocket();
	MySocket * clientsocket = new MySocket();
	
	mysocket->mybind();
	mysocket->mylisten();
 
	while(1){
	clientsocket->m_socket = mysocket->myaccept();
	clientsocket->Start();
	//clientsocket->run();
	// _beginthread( receive, 0, clientsocket );
	// mysocket->myrecv(socket);
	clientsocket->myrecv();
	}
	mysocket->myclose();
	system("pause");
	
}

5.mysocket.cpp

#include <Winsock2.h>
#include <windows.h>
#include <ws2tcpip.h>
#include <iostream>
#include "mysocket.h"
#pragma comment(lib, "ws2_32.lib") //socket编程需要引用该库
struct LoginData{
  char username[100];
  int password;
};
MySocket::MySocket(){
	this->init();
}
MySocket::~MySocket(){
}
 void MySocket::init(){
  WSADATA wsa_data; //WSADATA变量,包含windows socket执行的信息
  int sys_fun_result = 0; 
	// 初始化winsock动态库(ws2_32.dll),MAKEWORD(2, 2)用于请求使用winsock2.2版本
 
sys_fun_result = WSAStartup(MAKEWORD(2, 2), &wsa_data);
if (sys_fun_result != 0) {
       std::cout << "WSAStartup() function failed: " << sys_fun_result << "\n";
       system("pause");
        return ;
    }
 
 m_socket=socket(PF_INET,SOCK_STREAM,0);//创建套接字
 std::cout<<"Winsock初始化成功"<<std::endl;
}
 
 void MySocket::mybind(){
	int sys_fun_result = 0;
	SOCKADDR_IN addr;
    addr.sin_family=AF_INET;
    //addr.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//ip地址
	addr.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
    addr.sin_port=htons(16001);//绑定端口
	bind(m_socket,(SOCKADDR*)&addr,sizeof(SOCKADDR));//绑定
	if (sys_fun_result == SOCKET_ERROR) {
         std::cout << "bind() function failed with error: " << WSAGetLastError() << "\n";
         closesocket(m_socket);
          WSACleanup();
          return ;
      }
 }
 void MySocket::mylisten(){
	 int sys_fun_result = 0;
    sys_fun_result = listen(m_socket, SOMAXCONN);//  SOMAXCONN 默认值 5  代表能够接收的最多的连接
   if (sys_fun_result == SOCKET_ERROR) {
          std::cout << "listen() function failed with error: " << WSAGetLastError() << "\n";
          closesocket(m_socket);
          return ;
     }
 }
 
 SOCKET MySocket::myaccept(){
	 SOCKET socket;
char ip_buf[IP_BUF_SIZE];
SecureZeroMemory(ip_buf, IP_BUF_SIZE);
 SOCKADDR_IN clientsocket;
    int len=sizeof(SOCKADDR);
	socket=accept(m_socket,(SOCKADDR*)&clientsocket,&len);
	 if (socket == INVALID_SOCKET) {
         std::cout << "accept() function failed with error: " << WSAGetLastError() << "\n";
         closesocket(m_socket);
          WSACleanup();
          system("pause");
         return socket;
     }
	 //ip地址转换
      inet_ntop(AF_INET, &clientsocket, ip_buf, IP_BUF_SIZE);
     std::cout << "client ip address: " << ip_buf << std::endl;
	 return socket;
 }
 void MySocket::mysend( char * ch){
	 int sys_fun_result = 0;
	 char * sendBuf = ch;
	// memset(sendBuf,0,sizeof(sendBuf));
;
     sys_fun_result= send(m_socket,sendBuf,208,0);
	 if(sys_fun_result==SOCKET_ERROR){
	   std::cout << "mysend() function failed with error: " << WSAGetLastError() << "\n";
	 }
	 std::cout<<"sys_fun_result ="<<sys_fun_result<<std::endl;
	 std::cout<<"strlen(sendBuf) ="<<strlen(sendBuf)<<std::endl;
	 std::cout<<"sizeof(sendBuf)="<<sizeof(sendBuf)<<std::endl;
	  std::cout<<sendBuf;
 }
 void MySocket::myrecv(){
	 char receiveBuf[208];
	  int sys_fun_result = 0;
	while(1){
	 memset(receiveBuf,0,sizeof(receiveBuf));
	 /*         当recv返回值小于0时,socket报错;
                当recv返回值大于0时,成功,返回值为接收到的数据长度;
                当recv返回值等于0时,表示此时connect已经关闭,没有接收到数据。*/
	 
     sys_fun_result=recv(m_socket,receiveBuf,sizeof(receiveBuf),0);//这里不能用 strlen(receiveBuf) 因为 strlen(receiveBuf)=0
  
	 if (sys_fun_result == SOCKET_ERROR)
		{
			std::cout<<"error with code = "<<WSAGetLastError()<<std::endl;
			//exit(1);
		}
	 //Sleep(5000);
	   printf("clientsockid = %d,datalength =%d,cmd=%d,username=%s,password=%d\n", m_socket,*((int*)(&receiveBuf[0])),*( (int *) (&receiveBuf[4]) ),&receiveBuf[8],*((int*)(&receiveBuf[108])) );
	}
 }
 void MySocket::myclose(){
      closesocket(m_con);//关闭
        WSACleanup();//释放资源的操作
 }
 void MySocket::myconnect(){
	 int sys_fun_result = 0;
    SOCKADDR_IN clientsock_in;
    clientsock_in.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
    clientsock_in.sin_family=AF_INET;
    clientsock_in.sin_port=htons(16001);
	sys_fun_result = connect(m_socket,(SOCKADDR*)&clientsock_in,sizeof(SOCKADDR));
 
	if (sys_fun_result == SOCKET_ERROR) {
          std::cout << "connect() function failed with error: " << WSAGetLastError() << "\n";
          WSACleanup();
          system("pause");
          return ;
      }
 }
 
 void MySocket::run(){
 	
   std::cout<<"mysocket"<<std::endl;
   	//Sleep(5000);
   this->myrecv();
 }

6 mythread.cpp

#include<process.h>
#include<iostream>
#include "mythread.h"
void MyThread::Start( ){

	 _beginthread( Callback , 0, this );
};
void  MyThread::Callback(void * p){
	      MyThread * obj = (MyThread *) p;
		  obj->run();
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值