用过winsock.h的人请进来,有兴趣的人也请进

hoowa 2003-12-18 04:45:23
希望有人能提供一个采用winsock制作(不是那些tcpserver组件)的信息服务端,支持thread就最好。

客户端使用telnet能连接上就行。

因为,这样的资料太难找了。一般可以找到的都是那些VCL的东西。

请赐教,谢谢
...全文
110 16 打赏 收藏 转发到动态 举报
写回复
用AI写文章
16 条回复
切换为时间正序
请发表友善的回复…
发表回复
hoowa 2003-12-19
  • 打赏
  • 举报
回复
整个服务端代码完了,代码能否运行先不管。
其代码的语法都没错误,而且目的很简单,就是从client收到数据后再把数据发回给client正好可以用telnet来连接。

他把几个class都写在一起了。

不过有几点我不明白(TCP状态下):
1.他的结构是从主代码生成一个线程,请注意是一个pThread,这个线程做为服务端,这个线程如果发现有人请求就再生成线程去处理请求。
2.这个一个线程在如果遇到错误,或重新启动后就会被关闭挂起重新启动,而处理每个用户请求的pCThread却没有挂起,销毁delete,这样是不是会有隐患?

欢迎大家来一起讨论
hoowa 2003-12-19
  • 打赏
  • 举报
回复
主代码下半段.cpp
void __fastcall TListenThread::Execute() //启动这个ListenThread
{
char buf[4096]; //设置缓存大小
struct sockaddr_in from; //for UDP
int nLen=sizeof(from),nSize=0; //for UDP
InitSocket(); //执行相关函数
CreateListenSocket(); //执行相关函数
SetListenSocket(); //执行相关函数
BindListenSocket(); //执行相关函数

//当采用UDP协议的时候的服务端
if(m_Protocol==UDP){
while(!Terminated){
int nSize=recvfrom(m_Socket,buf,4096,0,(struct sockaddr*)&from,&nLen);
if(nSize>0){
buf[nSize]='\0';
PSTNForm->Memo1->Lines->Add("Received Length:"+String(nSize));
PSTNForm->Memo1->Lines->Add("Received:"+StrPas(buf));
::Sleep(100);
sendto(m_Socket,buf,nSize,0,(struct sockaddr*)&from,sizeof(struct sockaddr_in));
}
else return;

}
}
//这个以下都是TCP协议的
ListenSocket();
struct sockaddr_in client;
int nLength=sizeof(struct sockaddr_in);
//当未结束状态循环处理请求
while(!Terminated){
int nError=select(1,&FDS,0,0,0);
if(nError<=0) Terminate(); //如果没有符合条件的就挂起线程
//当有请求进来的时候
SOCKET m_AcceptSocket=accept(m_Socket,(struct sockaddr*)&client,&nLength);
if(m_AcceptSocket==INVALID_SOCKET){ //如果错误的请求就如何处理...
sprintf(szTmp,"Failed to execute accept,error no:%d",::WSAGetLastError());
::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR);
DoError();
Terminate();
return;
}
//执行通信组件
TCommunication *pCThread=new TCommunication(m_AcceptSocket,FALSE);
//挂起pCThread线程
pCThread->Terminate();
pCThread->WaitFor();
}
}

//---------------------------------------------------------------------------
// 界面部分的控制事件
//---------------------------------------------------------------------------
__fastcall TPSTNForm::TPSTNForm(TComponent* Owner)
: TForm(Owner)
{
}
//---------------------------------------------------------------------------
void __fastcall TPSTNForm::Button1Click(TObject *Sender)
{
Close();
}
//---------------------------------------------------------------------------
void __fastcall TPSTNForm::Button2Click(TObject *Sender)
{
if(pThread){ //如果pThread为真的情况下就挂起,停止,销毁掉,并重新初始化
pThread->Suspend();
pThread->Terminate();
delete pThread;
pThread=0;
}

//以下内容是获得端口的方法并且将端口号存储在m_Port中
UINT m_Port;
try
{
m_Port=Port->Text.ToInt();
}
catch(Exception &e)
{
::MessageBox(0,e.Message.c_str(),"Error",MB_OK+MB_ICONERROR);
return;
}

//以下是获得所选协议类型的语法
PROTO m_Protocol;
switch(Prot->ItemIndex)
{
case 0:
m_Protocol=TCP;
break;
case 1:
m_Protocol=UDP;
break;
default:
break;
}
//构造对象pThread并且将协议端口都给传递过去
pThread=new TListenThread(m_Protocol,m_Port,FALSE);
//pThread->Terminate();
}
//---------------------------------------------------------------------------
void __fastcall TPSTNForm::FormCreate(TObject *Sender)
{
::SendMessage(Prot->Handle,CB_SETCURSEL,0,1);
}
//---------------------------------------------------------------------------
void __fastcall TPSTNForm::FormDestroy(TObject *Sender)
{
if(pThread){
pThread->Suspend();
pThread->Terminate();}
}
//---------------------------------------------------------------------------
gf109 2003-12-19
  • 打赏
  • 举报
回复
请继续
hoowa 2003-12-19
  • 打赏
  • 举报
回复
主代码上半段.cpp
//---------------------------------------------------------------------------

#include <vcl.h>
#pragma hdrstop

#include "Unit1.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
#pragma resource "*.dfm"
TPSTNForm *PSTNForm;
TlistenThread *pThread=0;
//---------------------------------------------------------------------------

//****************************************************
// CLASS TCommunication For TCP
//****************************************************
__fastcall TCommunication::TCommunication(SOCKET m_Socket,bool CreateSuspended):TThread(FALSE)
{
m_AcceptSocket=m_Socket; //对象传递
szTmp[0]='\0';
FreeOnTerminate=true; //当停止了就自动挂起
}
__fastcall TCommunication::~TCommunication()
{
// closesocket(m_AcceptSocket);
}
void __fastcall TCommunication::Execute()
{
char buf[4096];
int nSize=0;
//接收数据包
nSize=recv(m_AcceptSocket,(char FAR*)buf,4096,0);
//如果数据包存在
if(nSize>0)
{
buf[nSize]='\0';
//Display
PSTNForm->Memo1->Lines->Add("Received Length:"+String(nSize));
PSTNForm->Memo1->Lines->Add("Received:"+StrPas(buf));
//Deliver休眠100秒再发送给这个客户端
::Sleep(100);
send(m_AcceptSocket,buf,nSize,0);
}

}

//*****************************************
// CLASS TListenThread
//****************************************
__fastcall TListenThread::TListenThread(PROTO m_ProtocolA,UINT m_PortA,bool CreateSuspended):TThread(FALSE)
{
m_Socket=INVALID_SOCKET; //先让主Socket设置成为无效的
m_Port=m_PortA; //在将端口信息拿来使用
m_Protocol=m_ProtocolA; //再使用协议信息
szTmp[0]='\0'; //错误信息,不知道干什么用
::ZeroMemory(&wsaData,sizeof(WSAData));
::ZeroMemory(&server,sizeof(struct sockaddr_in));
FreeOnTerminate=TRUE; //当终止的时候就自动删除
}

__fastcall TListenThread::~TListenThread()
{
closesocket(m_Socket);
::WSACleanup();
m_Socket=INVALID_SOCKET;
m_Port=0;
m_Protocol=TCP;
szTmp[0]='\0';
::ZeroMemory(&wsaData,sizeof(WSAData));
::ZeroMemory(&server,sizeof(struct sockaddr_in));
}
void __fastcall TListenThread::DoError()
{
if(m_Socket!=INVALID_SOCKET) closesocket(m_Socket);
WSACleanup();
return;
}
void __fastcall TListenThread::InitSocket() //初始化Socket
{
//检测版本是否符合要求
WORD version=MAKEWORD(2,0);
if(::WSAStartup(version,&wsaData)){
sprintf(szTmp,"Failed to intiailize socket,error no:%d",::WSAGetLastError());
::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR);
DoError();
return;
}
}
void __fastcall TListenThread::CreateListenSocket() //初始化第二步
{
//选择协议
switch(m_Protocol)
{
case UDP:
m_Socket=socket(AF_INET,SOCK_DGRAM,0);
break;
case TCP:
m_Socket=socket(AF_INET,SOCK_STREAM,0);
break;
default:
sprintf(szTmp,"Error protocol!");
::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR);
DoError();
break;
}
//测试选择是否成功
if(m_Socket==INVALID_SOCKET){
sprintf(szTmp,"Failed to create socket!");
::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR);
DoError();
return;
}
}
void __fastcall TListenThread::SetListenSocket() //初始化第三步
{
server.sin_family=AF_INET; //协议族
server.sin_port=htons(m_Port); //端口
server.sin_addr.S_un.S_addr=INADDR_ANY; //IP地址(自由选择)
//检测是否参数正确
int NewOpenType=SO_SYNCHRONOUS_NONALERT;
if(setsockopt(INVALID_SOCKET,SOL_SOCKET,SO_OPENTYPE,(char*)&NewOpenType,4)){
sprintf(szTmp,"Set socket option error,error no:%d",::WSAGetLastError());
::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR);
DoError();
return;
}
}
void __fastcall TListenThread::BindListenSocket() //初始化第四步
{
//绑定端口到IP地址上
if(bind(m_Socket,(sockaddr*)&server,sizeof(struct sockaddr_in))){
sprintf(szTmp,"Failed to bind socket,error no:%d",::WSAGetLastError());
::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR);
DoError();
return;
}

}
void __fastcall TListenThread::ListenSocket()
{
//开始监听端口了
if(listen(m_Socket,SOMAXCONN)){
sprintf(szTmp,"listen error,error no:%d",::WSAGetLastError());
::MessageBox(0,szTmp,"Error",MB_OK+MB_ICONERROR);
DoError();
return;
}
//检查端口是否在可写可读状态 Determine whether there is any connection
FD_ZERO(&FDS);
FD_SET(m_Socket,&FDS);
}
hoowa 2003-12-19
  • 打赏
  • 举报
回复
我这里有一个真正的winsock API程序,大家可以做一下研究。其实网上早有了,可惜没有注释,我做了一下注释。
.h头文件
//---------------------------------------------------------------------------

#ifndef Unit1H
#define Unit1H
//---------------------------------------------------------------------------
#include <Classes.hpp>
#include <Controls.hpp>
#include <StdCtrls.hpp>
#include <Forms.hpp>
#include <stdio.h>
#include "winsock.h"
//---------------------------------------------------------------------------
class TPSTNForm : public TForm
{
__published: // IDE-managed Components
TEdit *Port;
TLabel *Label1;
TButton *Button1;
TButton *Button2;
TMemo *Memo1;
TComboBox *Prot;
TLabel *Label2;
void __fastcall Button1Click(TObject *Sender);
void __fastcall Button2Click(TObject *Sender);
void __fastcall FormCreate(TObject *Sender);
void __fastcall FormDestroy(TObject *Sender);
private: // User declarations
public: // User declarations
__fastcall TPSTNForm(TComponent* Owner);
};
enum PROTO {TCP,UDP};

//---------------------------------------------------------
//---------------------TCP通信类线程-----------------------
//---------------------------------------------------------
class TCommunication:public TThread
{
private:
SOCKET m_AcceptSocket;
char szTmp[256]; //错误信息
public:
__fastcall TCommunication(SOCKET m_Socket,bool CreateSuspended);
__fastcall ~TCommunication();
protected:
virtual void __fastcall Execute();
};

//---------------------------------------------------------
//------------------------监听线程类-----------------------
//---------------------------------------------------------
class TListenThread:public TThread
{
private:
WSAData wsaData;
struct sockaddr_in server;
fd_set FDS; //检测哪个端口可读
UINT m_Port; //端口
PROTO m_Protocol; //协议
char szTmp[256]; //Error Message
public:
SOCKET m_Socket; //创造一个主Socket
void __fastcall DoError();
void __fastcall InitSocket(); //初始化Socket
void __fastcall CreateListenSocket(); //建立监听Socket
void __fastcall SetListenSocket(); //设置监听Socket
void __fastcall BindListenSocket(); //绑定到IP地址上
void __fastcall ListenSocket(); //监听Socket

public:
__fastcall TListenThread(PROTO m_ProtocolA,UINT m_PortA,bool CreateSuspended);
virtual __fastcall ~TListenThread();
protected:
virtual void __fastcall Execute();
};
//---------------------------------------------------------------------------
extern PACKAGE TPSTNForm *PSTNForm;
//---------------------------------------------------------------------------
#endif
hoowa 2003-12-19
  • 打赏
  • 举报
回复
socket api 写的阻塞线程server
那个就不能用了,他用的是serversocket这个组件的灵活性比较差。

看indy组件的source是一个好方法,可是如果水平不够呢?

socket api 写的 IOCP 模式的server,我这里网络有问题还未下载下来。

网上介绍winsock的资料不少,可惜没有适用的。
caimouse 2003-12-19
  • 打赏
  • 举报
回复
FastBT特点:
1.用C++编写,是目前唯一用C++写的BT下载程序。
2.占用系统资源少,比原来BT下载程序减少很多系统CPU资源。
3.可以同时多文件下载。
4.用多线程技术,大大提高多用户下载。
5.增加查看线程功能.
6.可以查看命令.

这么好用软件,立即下载!
FastBT下载 1.0.3.61版 2003.12.18

http://www.eyeteck.com/caimouse/web/BT.htm
hoowa 2003-12-19
  • 打赏
  • 举报
回复
xjb2001(痴墨) 说的是啊,这个代码,我用了足足的半天时间才从乱七八糟的文档中分离出来。
我还在忧郁,这个代码是否就是VC代码呢。呵呵:)

有入门资料太好了。我还没看过呢,现在就去看
xjb2001 2003-12-19
  • 打赏
  • 举报
回复
代码看了,写的一般,层次不好

写这代码的兄弟估计是用VC的
会划开类,但是类的内部控制比较乱

喜欢堆代码

不推荐
xjb2001 2003-12-19
  • 打赏
  • 举报
回复
看飞云兄的代码前
先看看入门的资料:

SOCKET入门必看:

http://www.mhdn.net/p/2002-09-11/5878.html
http://www.mhdn.net/p/2002-09-11/5880.html
http://www.mhdn.net/p/2002-09-11/5882.html
pzoon 2003-12-18
  • 打赏
  • 举报
回复
UP
constantine 2003-12-18
  • 打赏
  • 举报
回复
顶,
短歌如风 2003-12-18
  • 打赏
  • 举报
回复
Indy组件的源代码不就是最好的例子?
pp616 2003-12-18
  • 打赏
  • 举报
回复
socket api 写的 IOCP 模式的server
http://expert.csdn.net/Expert/TopicView1.asp?id=2563448
socket api 写的阻塞线程server
http://expert.csdn.net/Expert/FAQ/FAQ_Index.asp?id=122123
warton 2003-12-18
  • 打赏
  • 举报
回复
vcbase
codeproject
chifengwatch 2003-12-18
  • 打赏
  • 举报
回复
你用搜索引擎搜winsock应该有一大堆。

1,317

社区成员

发帖
与我相关
我的任务
社区描述
C++ Builder 网络及通讯开发
社区管理员
  • 网络及通讯开发社区
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
暂无公告

试试用AI创作助手写篇文章吧