基於UDP的多線程網絡通信程序

   分享一段基於UDP的多線程網絡點對點通信程序。

  文件一:CComm.h

#ifndef _CCOMM_H_
#define _CCOMM_H_

#include <string.h>
#include <stdio.h>
#include <stdlib.h>

#include <winsock.h>
#define socklen_t	int
#pragma comment(lib, "wsock32.lib")

class CComm
{
private:
	static void *ListenThread(void *data);
	SOCKET ListenSocket;	// 等待接收數據的socket
	sockaddr_in srv;			// 綁定地址
	sockaddr_in client;			// 發送數據過來的地址

public:
	CComm();
	~CComm();

	bool SendMsg(char *Msg, int Len, char *host, short port);
	bool Listen(int PortNum);

};

#endif	// #define _CCOMM_H_


文件一:CComm.cpp


#include "CComm.h"


CComm::CComm()
{
	//構造函數
	ListenSocket = INVALID_SOCKET;	// 開始設置爲INVALID_SOCKET
	
	#ifdef _WIN32	// 如果是win32系統
		WORD VersionRequested = MAKEWORD(1,1);
		WSADATA wsaData;
		
		WSAStartup(VersionRequested, &wsaData);	// 啓動winsock服務
		if ( wsaData.wVersion != VersionRequested )
		{
			printf("Wrong version or WinSock not loaded\n");
			fflush(0);	
		}
	#endif
}

//析構函數
CComm::~CComm()
{
	if ( ListenSocket != INVALID_SOCKET )
		closesocket( ListenSocket );	// 如果已經創建、則關閉

	#ifdef _WIN32	// 調用WSACleanup
		WSACleanup();
	#endif
}

bool CComm::SendMsg( char *Msg, int Len, char *host, short port )
{
	signed int Sent;
	hostent *hostdata;
	if ( atoi(host) )	// 是否IP地址爲標準形式
	{
		u_long ip = inet_addr( host );
		hostdata = gethostbyaddr( (char *)&ip, sizeof(ip), PF_INET );
	}
	else	// 否則則可能是機器名
	{
		hostdata = gethostbyname( host );
	}

	if ( !hostdata )
	{
		printf("獲得機器名錯誤\n");
		fflush(0);
		return false;
	}

	sockaddr_in dest;	// 發送目標地址
	dest.sin_family = PF_INET;
	dest.sin_addr = *(in_addr *)(hostdata->h_addr_list[0]);
	dest.sin_port = htons( port );
	printf("信息已經被髮送到主機 %s 端口爲 %i\n", inet_ntoa(dest.sin_addr), ntohs(dest.sin_port));
	//數據發送
	Sent = sendto(ListenSocket, Msg, Len, 0, (sockaddr *)&dest, sizeof(sockaddr_in));
	
	if ( Sent != Len )
	{
		printf("錯誤發送UDP信息\n");
		fflush(0);
		return false;
	}
	
	return true;
}

void *CComm::ListenThread( void *data )
{
	char buf[4096];
	CComm *Comm = (CComm *)data;
	int len = sizeof(Comm->client);
	while(1)	// 一直循環
	{
		//接收數據
		int result = recvfrom( Comm->ListenSocket, buf, sizeof(buf)-1, 0, (sockaddr *)&Comm->client, (socklen_t *)&len);
		if ( result > 0 )
		{
			buf[result] = 0;
			printf("Message received from host %s port %i\n", inet_ntoa(Comm->client.sin_addr), ntohs(Comm->client.sin_port));
			printf(">> %s", buf);
			fflush(0);
		}	
	}	
}


//地址綁定,注意在UDP協議中,不需要listen,這裏函數listen只是綁定一個端口
bool CComm::Listen( int PortNum )
{
	ListenSocket = socket(PF_INET, SOCK_DGRAM, 0);
	if ( ListenSocket == INVALID_SOCKET )
	{
		printf("Error: socket創建失敗\n");
		fflush(0);
		return false;
	}

	srv.sin_family = PF_INET;
	srv.sin_addr.s_addr = htonl( INADDR_ANY );	// 任何地址
	srv.sin_port = htons( PortNum );

	if ( bind( ListenSocket, (struct sockaddr *)&srv, sizeof(srv)) != 0 )
	{
		printf("Error: 綁定失敗\n");
		fflush(0);
		closesocket( ListenSocket );
		return false;
	}

	int ThreadID;	// 線程id
	
		DWORD thread;
		//調用createthread創建線程
		ThreadID = (int)CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(CComm::ListenThread), (void *)this, 0, &thread);
		ThreadID = ThreadID ? 0 : 1;	// 如果成功,則返回爲0

	if(ThreadID)	// ThreadID如果不爲0,則線程創建失敗
	{
		printf("線程創建失敗\n");
		return false;
	}
	else
		return true;
}



發佈了83 篇原創文章 · 獲贊 5 · 訪問量 14萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章