C++socket编程Word文档格式.docx

上传人:b****5 文档编号:21405523 上传时间:2023-01-30 格式:DOCX 页数:63 大小:344.25KB
下载 相关 举报
C++socket编程Word文档格式.docx_第1页
第1页 / 共63页
C++socket编程Word文档格式.docx_第2页
第2页 / 共63页
C++socket编程Word文档格式.docx_第3页
第3页 / 共63页
C++socket编程Word文档格式.docx_第4页
第4页 / 共63页
C++socket编程Word文档格式.docx_第5页
第5页 / 共63页
点击查看更多>>
下载资源
资源描述

C++socket编程Word文档格式.docx

《C++socket编程Word文档格式.docx》由会员分享,可在线阅读,更多相关《C++socket编程Word文档格式.docx(63页珍藏版)》请在冰豆网上搜索。

C++socket编程Word文档格式.docx

因此,TCP提供了可靠的应用数据传输服务。

通信双方使用TCP传输的一般过程参考如图3.2。

图3.2TCP通信的一般过程

本节将要实现一个TCP传输的演示程序TCPDemo,它包括服务器和客户机两个部分。

它们的程序界面如图3.3。

图3.3TCP传输演示程序界面

TCPDemo的演示过程如下:

(1)将服务器和客户机两部分程序都运行起来(此时服务器已经启动了侦听客户机连接请求的子线程,侦听端口号为10028)。

(2)在客户机程序界面上输入服务器的IP地址(如果服务器和客户机运行在同一台机器上,IP地址可以指定为127.0.0.1)、侦听端口号(因为服务器在10028端口上侦听,这里也应该指定为10028)。

(3)点击客户机程序界面上的“Connect”按钮,向服务器发送Socket连接请求。

(4)服务器侦听到有客户机的连接请求后便接受它(于是在两个程序之间就建立了一条可靠的Socket连接)。

然后服务器会向客户机发送两次字符串数据。

(5)客户机接收到数据后,弹出两次如图3.4的消息框。

图3.4TCP传输客户机接收到数据后显示的消息框

TCPDemo为什么使用10028作为TCP通信的端口号?

因为TCP数据包的TCP头结构中,使用了16位的域来表示一个端口号。

因此,有65536个可能的端口号。

不过,0-1023是周知口(众所周知的端口,比如80是超文本传输协议http的端口,25是简单邮件传输协议smtp的端口,20和21是文件传输协议ftp的端口等),比1023大的端口号通常被称为高端口号。

应用程序一般使用高端口号提供自己的通信服务。

TCPDemo使用10028端口是偶然的,只要比1023大就可以了。

TCPDemo在具体实现时,设计了一个CTCPListener类专门用于服务器对特定TCP端口的侦听。

另外,设计了一个CStreamSocket类专门用于TCP数据的传输。

CStreamSocket作为基类,服务器程序从它派生出另一个类CSocketSender专门用于数据的发送,客户机程序从它派生出CSocketReceiver类专门用于数据的接收。

这些类的继承结构如图3.5。

图3.5TCPDemo的类继承结构

关于CMsgStation和CMsgReceiver两个类的功能介绍,请读者另行参考本书的“2.4.1一种不错的设计模式”。

//

//CTCPListener.h

#ifndef__H_CTCPListener__

#define__H_CTCPListener__

#include"

CMsgStation.h"

classCTCPListener:

publicCMsgStation

{

protected:

SOCKETmListener;

//用于侦听的Socket

SOCKETmAccepted;

//用于与远程端建立连接的Socket

WORDmListenPort;

//侦听端口号

BOOLmIsListening;

//是否正在侦听的标记

HANDLEmLsnThread;

//侦听线程

public:

CTCPListener();

virtual~CTCPListener();

//设置/得到侦听的端口号

voidSetListenPort(WORDinPort);

WORDGetListenPort(void);

//创建/销毁用于侦听的Socket

BOOLCreate(void);

voidDeleteListener(void);

//销毁服务器与客户机建立连接的Socket

voidDeleteAccepted(void);

//启动/停止侦听线程

BOOLStartListening(void);

voidStopListening(void);

//得到服务器与客户机建立连接的Socket(用于数据传输)

SOCKETGetAccepted(void);

private:

BOOLAccept(void);

//接受远程端的连接请求

staticDWORDWINAPIListeningThrd(void*pParam);

//侦听线程执行体

};

#endif//__H_CTCPListener__

//

//CTCPListener.cpp

stdafx.h"

CTCPListener.h"

Netdefs.h"

#ifdef_DEBUG

#definenewDEBUG_NEW

#undefTHIS_FILE

staticcharTHIS_FILE[]=__FILE__;

#endif

//////////////////////////////////////////////////////////////////////////////

CTCPListener:

:

CTCPListener()

//参数初始化

mListener=INVALID_SOCKET;

mAccepted=INVALID_SOCKET;

//默认在10028端口上侦听

mListenPort=10028;

mLsnThread=NULL;

mIsListening=FALSE;

}

~CTCPListener()

//销毁Socket

DeleteAccepted();

DeleteListener();

//停止侦听线程

StopListening();

//设置侦听端口号

voidCTCPListener:

SetListenPort(WORDinPort)

mListenPort=inPort;

//得到侦听端口号

WORDCTCPListener:

GetListenPort(void)

returnmListenPort;

//创建用于侦听的Socket

BOOLCTCPListener:

Create(void)

//销毁侦听Socket

intval=0;

BOOLpass=FALSE;

//创建一个TCP传输的Socket

mListener=socket(PF_INET,SOCK_STREAM,IPPROTO_TCP);

if(mListener!

=INVALID_SOCKET)

{

//在Socket上进行参数设置

BOOLsopt=TRUE;

setsockopt(mListener,IPPROTO_TCP,TCP_NODELAY,

(char*)&

sopt,sizeof(BOOL));

//在销毁Socket时不必等待未发送完的数据完全发送出去

setsockopt(mListener,SOL_SOCKET,SO_DONTLINGER,

//绑定Socket到指定的侦听端口

SOCKADDR_INaddr;

memset(&

addr,0,sizeof(SOCKADDR_IN));

addr.sin_family=AF_INET;

addr.sin_addr.s_addr=htonl(INADDR_ANY);

addr.sin_port=htons(mListenPort);

val=bind(mListener,(structsockaddr*)&

addr,sizeof(addr));

pass=(val!

=SOCKET_ERROR);

}

if(pass)

//将Socket置于侦听状态

val=listen(mListener,SOMAXCONN);

if(!

pass)

DeleteListener();

returnpass;

//销毁用于侦听的Socket

DeleteListener(void)

closesocket(mListener);

mListener=INVALID_SOCKET;

//销毁服务器与客户机建立连接的Socket

DeleteAccepted(void)

if(mAccepted!

closesocket(mAccepted);

mAccepted=INVALID_SOCKET;

//启动侦听线程(因为用于接受连接请求的accept函数调用时会阻塞)

StartListening(void)

//如果侦听Socket没有创建,则创建它

if(mListener==INVALID_SOCKET)

Create();

if(mIsListening)

{

returnTRUE;

}

//启动侦听线程

DWORDthreadID=0;

mLsnThread=CreateThread(NULL,0,ListeningThrd,

this,0,&

threadID);

return(mLsnThread!

=NULL);

returnFALSE;

//停止侦听线程

StopListening(void)

=INVALID_SOCKET&

&

mIsListening)

//销毁侦听Socket,于是accept将脱离阻塞状态

//等待侦听线程完全退出

if(mLsnThread!

=NULL)

WaitForSingleObject(mLsnThread,INFINITE);

mLsnThread=NULL;

//接受远程端的连接请求(创建一个新的Socket用于与远程端建立一条连接)

Accept(void)

SOCKADDR_INsaddr;

intlen=sizeof(SOCKADDR_IN);

//侦听远程端的连接请求(如果没有连接请求,这个函数将阻塞)

SOCKETaccepted=accept(mListener,(SOCKADDR*)&

saddr,&

len);

if(accepted==INVALID_SOCKET)

returnFALSE;

//注意:

目前仅支持建立一条Socket连接!

//在建立新的连接之前将以前的连接断开

DeleteAccepted();

//保存与远程端建立连接的Socket

mAccepted=accepted;

//在Socket上设置一些参数

setsockopt(mAccepted,IPPROTO_TCP,TCP_NODELAY,

setsockopt(mAccepted,SOL_SOCKET,SO_DONTLINGER,

returnTRUE;

//当与远程端连接的Socket取出之后,保存该Socket的变量置为无效

//取出的Socket由取出者负责销毁

SOCKETCTCPListener:

GetAccepted(void)

SOCKETret=mAccepted;

returnret;

//侦听线程的函数执行体

DWORDWINAPICTCPListener:

ListeningThrd(void*pParam)

ASSERT(pParam);

//获得侦听对象指针

CTCPListener*pListen=(CTCPListener*)pParam;

pListen->

mIsListening=TRUE;

while(pListen->

mIsListening)

//开始侦听(如果没有远程端发送连接请求,这个函数将阻塞)

if(!

pListen->

Accept())

pListen->

mIsListening=FALSE;

break;

else

//constlongcNewSocketAccepted=6688;

//发送给上层观察者一个自定义消息cNewSocketAccepted,

//表示一条Socket连接已经建立(可以用它进行数据传输了!

Broadcast(cNewSocketAccepted);

return1;

//CStreamSocket.h

#ifndef__H_CStreamSocket__

#define__H_CStreamSocket__

classCStreamSocket

SOCKETmSocket;

//用于数据发送或接收的Socket

BOOLmIsConnected;

//Socket是否已经建立了连接的标记

BOOLmIsReceiving;

//使用独立的线程进行数据接收

HANDLEmRcvThread;

BOOLmIsSending;

//使用独立的线程进行数据发送

HANDLEmSndThread;

CStreamSocket();

virtual~CStreamSocket();

BOOLAttach(SOCKETinSocket);

//关联一个Socket

voidDetach(void);

//向指定IP地址、端口号的机器发送连接请求

BOOLConnectTo(constchar*inTarget,WORDinPort);

BOOLIsConnected(void){returnmIsConnected;

};

//用于数据接收的控制函数

BOOLStartReceiving(void);

voidStopReceiving(void);

BOOLIsReceiving(void){returnmIsReceiving;

//用于数据发送的控制函数

BOOLStartSending(void);

voidStopSending(void);

BOOLIsSending(void){returnmIsSending;

staticDWORDWINAPIReceivingThrd(void*pParam);

//接收线程执行体

staticDWORDWINAPISendingThrd(void*pParam);

//发送线程执行体

//接收/发送数据循环过程(虚函数,供子类定制)

virtualvoidReceivingLoop(void);

virtualvoidSendingLoop(void);

#endif//__H_CStreamSocket__

//CStreamSocket.cpp

CStreamSocket.h"

UNetwork.h"

CStreamSocket:

CStreamSocket()

{

mSocket=INVALID_SOCKET;

mIsConnected=FALSE;

mIsReceiving=FALSE;

mIsSending=FALSE;

mRcvThread=NULL;

mSndThread=NULL;

//销毁Socket,停止发送/接收线程

~CStreamSocket()

Detach();

StopSending();

StopReceiving();

//关联一个Socket到本包装对象

BOOLCStreamSocket:

Attach(SOCKETinSocket)

//如果已经包装了一个Socket,则返回一个错误值

if(mSocket!

returnFALSE;

//保存Socket句柄

mSocket=inSocket;

mIsConnected=TRUE;

returnTRUE;

//销毁Socket

voidCStreamSocket:

Detach(void)

closesocket(mSocket);

mSocket=INVALID_SOCKET;

mIsConnected=FALSE;

//向指定IP地址、端口号的机器发送连接请求

ConnectTo(constchar*inTarget,WORDinPort)

if(mIsConnected)

//首先创建一个TCP传输的Socket

mSocket=socket(AF_INET,SOCK_STREAM,IPPROTO_TCP);

//在成功创建的Socket上调整参数

setsockopt(mSocket,IPPROTO_TCP,TCP_NODELAY,

setsockopt(mSocket,SOL_SOCKET,SO_DONTLINGER,

//向服务器发送连接请求

saddr,0,sizeof(SOCKADDR_IN));

saddr.sin_addr.S_un.S_addr=inet_addr(inTarget);

saddr.sin_family=AF_INET;

saddr.sin

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 工程科技 > 冶金矿山地质

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1