c++网络编程

客户端:

// Client.cpp
#include "stdafx.h"
#include <windows.h>
#include <process.h>
#include <iostream>
using
namespace std;
#pragma comment(lib,"ws2_32.lib")
//接收数据
void Receive(PVOID param)
{   
	char buf[2096]; 
	while(1)  
	{      
		SOCKET* sock=(SOCKET*)param;  
		int bytes;  
		if((bytes=recv(*sock,buf,sizeof(buf),0))==SOCKET_ERROR)
		{        
			printf("接收数据失败!\n"); 
			exit(-1);    
		}      
		buf[bytes]='\0';  
		cout<<"服务器说:"<<buf<<endl;    
	}
}//获取服务器IP
unsigned long GetServerIP(void)
{    
	//把字符串的IP地址转化为u_long
	char ipStr[20];  
	//用第二个参数填充第一个参数所指的内存,填充的长度为第三个参数的大小  
	memset(ipStr,0,sizeof(ipStr));
	cout<<"请输入你要链接的服务器IP:";  
	cin>>ipStr;   
	unsigned long ip; 
	if((ip=inet_addr(ipStr))==INADDR_NONE)
	{     
		cout<<"不合法的IP地址:";    
		Sleep(3000);    
		exit(-1); 
	}  
	return ip;}
//链接服务器
void Connect(SOCKET &sock)
{   
	unsigned long ip=GetServerIP();  
	//把端口号转化成整数
	short port=1986;
	cout<<"Connecting to "<<inet_ntoa(*(in_addr*)&ip)<<" : "<<port<<endl; 
	struct sockaddr_in serverAddress;  
	memset(&serverAddress,0,sizeof(sockaddr_in)); 
	serverAddress.sin_family=AF_INET;    
	serverAddress.sin_addr.S_un.S_addr= ip;  
	serverAddress.sin_port = htons(port);    
	//建立和服务器的连接
	if(connect(sock,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR)
	{        
		cout<<"建立连接失败:"<<WSAGetLastError();  
		Sleep(3000);      
		exit(-1);  
	}
}
//发送数据
void SendMsg(SOCKET &sock)
{ 
	char buf[2048];   
	while(1)
	{   
		//从控制台读取一行数据 
		gets_s(buf);     
		cout<<"我说:"; 
		//发送给服务器
		if(send(sock,buf,strlen(buf),0)==SOCKET_ERROR)
		{        
			cout<<"发送数据失败!";
			exit(-1);     
		}   
	}
}
int main(int argc, char* argv[])
{  
	WSADATA wsa;    
	//初始化套接字DLL
	if(WSAStartup(MAKEWORD(2,2),&wsa)!=0)
	{      
		cout<<"套接字初始化失败!";    
		Sleep(3000);  
		exit(-1); 
	}     
	//创建套接字 
	SOCKET sock;  
	if((sock=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
	{       
		cout<<"创建套接字失败!";       
		exit(-1);  
	}   
	Connect(sock);
	//链接服务器    
	_beginthread(Receive,0,&sock);
	//启动接收数据线程 
	SendMsg(sock);
	//发送数据     
	//清理套接字占用的资源  
	WSACleanup(); 
	return 0;
}


服务端:

// Service.cpp : 定义控制台应用程序的入口点。
//

// Server.cpp : 定义控制台应用程序的入口点。 
#include "stdafx.h"
#include <windows.h>
#include <process.h>
#include <iostream>
#include "FileLog.h"
#include "time.h"
using namespace std;
#pragma comment(lib,"ws2_32.lib")//多线程调用的方法只有一个指针型的参数,有时候需要多个参数,所以定义一个结构,参数作为结构的字段
typedef struct _receiveStruct
{  
	SOCKET *Socket;  
	FileLog *fileLog;   
	_receiveStruct(SOCKET *_socket,FileLog *_fileLog):Socket(_socket),fileLog(_fileLog){}
} ReceiveStruct;
//获取今天日期的字符串
string GetDate(const char*format)
{    
	time_t tm;    
	struct tm *now; 
	char timebuf[20]; 
	time(&tm);   
	now=localtime(&tm);  
	strftime(timebuf,sizeof(timebuf)/sizeof(char),format,now); 
	return string(timebuf);
}
//接收数据线程
void receive(PVOID param)
{
	ReceiveStruct* receiveStruct=(ReceiveStruct*)param;  
	char buf[2048];  
	int bytes;   
	while(1)  
	{     
		//接收数据
		if((bytes=recv(*receiveStruct->Socket,buf,sizeof(buf),0))==SOCKET_ERROR)
		{           
			cout<<"接收数据失败!\n"; 
			_endthread();//终止当前线程   
		}       
		buf[bytes]='\0';   
		cout<<"客户端说:"<<buf<<endl;     
		receiveStruct->fileLog->Write("客户端    ").WriteLine(GetDate("%Y-%m-%d %H:%M:%S").c_str()).WriteLine(buf);//记录聊天内容    
	}
}
//获取本机IP
in_addr getHostName(void) 
{    
	char host_name[255]; 
	//获取本地主机名称
	if (gethostname(host_name, sizeof(host_name)) == SOCKET_ERROR) 
	{      
		cout<<"Error %d when getting local host name."<<WSAGetLastError();   
		Sleep(3000);     
		exit(-1);  
	}        
	//从主机名数据库中得到对应的“IP”
	struct hostent *phe = gethostbyname(host_name);  
	if (phe ==0)
	{       
		cout<<"Yow! Bad host lookup.";   
		Sleep(3000);       
		exit(-1);   
	}   
	struct in_addr addr; 
	memcpy(&addr, phe->h_addr_list[0], sizeof(struct in_addr)); 
	return addr;
}
//启动服务器
SOCKET StartServer(void)
{    
	//创建套接字
	SOCKET serverSocket;  
	if((serverSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP))==INVALID_SOCKET)
	{     
		cout<<"创建套接字失败!"; 
		Sleep(3000);   
		exit(-1);  
	}  
	short port=1986;   
	struct sockaddr_in serverAddress;  
	//初始化指定的内存区域   
	memset(&serverAddress,0,sizeof(sockaddr_in));
	serverAddress.sin_family=AF_INET; 
	serverAddress.sin_addr.S_un.S_addr = htonl(INADDR_ANY);    
	serverAddress.sin_port = htons(port); 
	//绑定
	if(bind(serverSocket,(sockaddr*)&serverAddress,sizeof(serverAddress))==SOCKET_ERROR)
	{       
		cout<<"套接字绑定到端口失败!端口:"<<port;
		Sleep(3000);  
		exit(-1);  
	}  
	//进入侦听状态
	if(listen(serverSocket,SOMAXCONN)==SOCKET_ERROR)
	{        
		cout<<"侦听失败!"; 
		Sleep(3000);    
		exit(-1);   
	}         
	//获取服务器IP
	struct in_addr addr = getHostName();    
	cout<<"Server "<<inet_ntoa(addr)<<" : "<<port<<" is listening......"<<endl;  
	return serverSocket;
}
//接收客户端连接
SOCKET ReceiveConnect(SOCKET &serverSocket)
{   
	SOCKET clientSocket;
	//用来和客户端通信的套接字
	struct sockaddr_in clientAddress;
	//用来和客户端通信的套接字地址  
	memset(&clientAddress,0,sizeof(clientAddress));
	//初始化存放客户端信息的内存
	int addrlen =sizeof(clientAddress);  
	//接受连接
	if((clientSocket=accept(serverSocket,(sockaddr*)&clientAddress,&addrlen))==INVALID_SOCKET)
	{        
		cout<<"接受客户端连接失败!";  
		Sleep(3000);     
		exit(-1);  
	}    
	cout<<"Accept connection from "<<inet_ntoa(clientAddress.sin_addr)<<endl; 
	return clientSocket;
}
//发送数据
void SendMsg(SOCKET &clientSocket,FileLog &fileLog)
{    
	char buf[2048];  
	while(1)
	{  
		cout<<"服务器说:";      
		gets_s(buf);       
		if(send(clientSocket,buf,strlen(buf),0)==SOCKET_ERROR)
		{
			cout<<"发送数据失败!"<<endl;       
			Sleep(3000);         
			exit(-1);    
		}     
		fileLog.Write("服务器   ").WriteLine(GetDate("%Y-%m-%d %H:%M:%S").c_str()).WriteLine(buf);
		//记录聊天内容  
	}
} 
int main(int argc, char* argv[])
{   
	WSADATA wsa;
	//WSADATA结构被用来保存函数WSAStartup返回的Windows Sockets初始化信息  
	//MAKEWORD(a,b)是将两个byte型合并成一个word型,一个在高8位(b),一个在低8位(a) 
	if(WSAStartup(MAKEWORD(2,2),&wsa)!=0)
	{      
		cout<<"套接字初始化失败!"; 
		Sleep(3000);     
		exit(-1);   
	}        
	SOCKET serverSocket=StartServer();
	//启动服务器  
	SOCKET clientSocket=ReceiveConnect(serverSocket);
	//接收客服端的链接   
	FileLog fileLog; 
	fileLog.Open(GetDate("%Y%m%d").append(".log").c_str());
	//打开记录聊天内容文件 
	ReceiveStruct receiveStruct(&clientSocket,&fileLog); 
	_beginthread(receive,0,&receiveStruct);
	//启动一个接收数据的线程  
	SendMsg(clientSocket,fileLog);
	//发送数据   
	fileLog.Close();
	//关闭文件    
	closesocket(clientSocket);
	//关闭客户端套接字(马上发送FIN信号,所有没有接收到或是发送完成的数据都会丢失)
	closesocket(serverSocket);
	//关闭服务器套接字  
	//清理套接字占用的资源 
	WSACleanup();  
	return 0;
}


FileLog.h:

#include "iostream"
#include "string.h"
#include <windows.h>
using namespace std;
class FileLog
{    
private: 
	CRITICAL_SECTION cs; 
	HANDLE fileHandle;   
	void Lock()     
	{           
		EnterCriticalSection(&cs);
		// 进入临界区    
	}       
	void UnLock()   
	{         
		LeaveCriticalSection(&cs);
		//离开临界区    
	}   
public:     
	FileLog()  
	{       
		InitializeCriticalSection(&cs);
		//初始化临界区  
		fileHandle=INVALID_HANDLE_VALUE;
		//先初始化为错误的句柄     
	}      
	~FileLog() 
	{         
		if(fileHandle!=INVALID_HANDLE_VALUE)   
		{       
			//CloseHandle的功能是关闭一个打开的对象句柄,该对象句柄可以是线程句柄,也可以是进程、信号量等其他内核对象的句柄  
			CloseHandle(fileHandle);    
		}     
		DeleteCriticalSection(&cs);
		//删除临界区   
	}       
	BOOL Open(const char*fileName);
	//打开文件    
	FileLog& Write(const char*content);
	//向文件中写入内容    
	FileLog& WriteLine(const char*content);
	//向文件中写入内容      
	BOOL Read(char*buf,int size);
	//读文件内容       
	BOOL Close();
	//关闭文件
};


FileLog.cpp:

#include "stdafx.h"
#include "FileLog.h"
//打开文件
BOOL FileLog::Open(const char*fileName)
{   
	if(fileHandle==INVALID_HANDLE_VALUE) 
	{   
		fileHandle=CreateFile(fileName,GENERIC_WRITE|GENERIC_READ,FILE_SHARE_READ|FILE_SHARE_WRITE,NULL,OPEN_ALWAYS,FILE_ATTRIBUTE_NORMAL,NULL);   
		if(fileHandle!=INVALID_HANDLE_VALUE)      
		{          
			SetFilePointer(fileHandle,0,NULL,FILE_END);       
			return TRUE; 
		}  
	}  
	return FALSE;}
//写文件 返回当前对象的引用,实现连接操作
FileLog& FileLog::Write(const char*content){   
	Lock();   
	if(fileHandle!=INVALID_HANDLE_VALUE)   
	{    
		DWORD dwSize=0; 
		WriteFile(fileHandle,content,strlen(content),&dwSize,NULL);
		//写
	}   
	//开始的时候少写了这句,由于加的锁没有释放,一个线程占用之后,导致其他线程只能一直等待,好久都没有找到原因。    
	UnLock();    
	return*this;
} 
//写入一行
FileLog& FileLog::WriteLine(const char*content)
{   
	Lock();
	if(fileHandle!=INVALID_HANDLE_VALUE)  
	{   
		DWORD dwSize=0;    
		WriteFile(fileHandle,content,strlen(content),&dwSize,NULL);
		//写  
	}   
	UnLock(); 
	return FileLog::Write("\r\n");
}

//读文件内容
BOOL FileLog::Read(char*buf,int size)
{  
	BOOL isOK=FALSE;
	Lock();  
	if(fileHandle!=INVALID_HANDLE_VALUE) 
	{      
		DWORD dwSize=0; 
		isOK=ReadFile(fileHandle,buf,size,&dwSize,NULL);
		//读    
	}   
	return isOK;
}
//关闭文件
BOOL FileLog::Close()
{   
	BOOL isOK=FALSE;
	Lock();
	if(fileHandle!=INVALID_HANDLE_VALUE)   
	{     
		isOK=CloseHandle(fileHandle);   
		fileHandle=INVALID_HANDLE_VALUE;  
	}    
	UnLock();  
	return isOK;
}


 

你可能感兴趣的:(c++网络编程)