socket编程环境,熟悉socket编程

http://www.itjxue.com  2023-01-22 21:06  来源:未知  点击次数: 

mfc socket 编程的流程是怎么样的?

初始化socket

首先需要调用AfxSocketInit()函数来初始化我们的socket环境。

为了初始化sockets,我们需要调用AfxSocketInit()函数。它通常是在MFC中的InitInstance()函数中被调用的。如果我们用程序向导来创建socket程序的话,查看“use Windows Sockets”这个选项,然后选中它。它将会自动的为我们创建这个步骤了。(如果我们没有选中这个选项的话,我们也可以手动添加这些代码的。)这个函数的返回值显示这个函数的调用成功或失败。

BOOL CServerApp::InitInstance()

{....

if( AfxSocketInit() == FALSE)

{

AfxMessageBox("Sockets Could Not Be Initialized");

return FALSE;

}

...

}

创建Server Sockets

为了创建一个Server Socket,我们需要声明一个CAyncSocket的变量或者我们自己定制的一个从AyncSocket或是Cscket继承来的类的类型的变量。然后调用Create()函数,同时指定监听的端口。这个函数的返回值显示这个函数的调用成功或失败。

UpdateData(TRUE);

m_sListener.Create(m_port);

if(m_sListener.Listen()==FALSE)

{

AfxMessageBox("Unable to Listen on that port,please try another port");

m_sListener.Close();

return;

}

创建Client Sockets

为了创建Client socket类,我们需要声明一个CAyncSocket的变量或者我们自己定制的一个从AyncSocket或是Cscket继承来的类的类型的变量。然后调用Create()函数,同时指定监听的端口。这个函数的返回值显示这个函数的调用成功或失败。

m_sConnected.Create();

m_sConnected.Connect("server ip",port);

监听客户端的连接

创建了server socket以后,我们要进行监听。调用Listen()函数。这个函数的返回值显示这个函数的调用成功或失败。

if( m_sListener.Listen()== FALSE)

{

AfxMessageBox("Unable to Listen on that port,please try another port");

m_sListener.Close();

return;

}

接受连接

连接请求要被接受accept,是用另外的socket,不是正在监听的socket。请参看代码。

void CXXXDlg::OnAccept()

{

CString strIP;

UINT port;

if(m_sListener.Accept(m_sConnected))

{

m_sConnected.GetSockName(strIP,port); //应该是GetPeerName,获取对方的IP和port

m_status="Client Connected,IP :"+ strIP;

m_sConnected.Send("Connected To Server",strlen("Connected To Server"));

UpdateData(FALSE);

}

else

{

AfxMessageBox("Cannoot Accept Connection");

}

}

发送数据

数据放在一个buffer中或是结构体中,调用send()函数发送。

m_sConnected.Send(pBuf,iLen);

接受数据

调用receive()接受数据。

void CXXXrDlg::OnReceive()

{

char *pBuf =new char [1025];

CString strData;

int iLen;

iLen=m_sConnected.Receive(pBuf,1024);

if(iLen == SOCKET_ERROR)

{

AfxMessageBox("Could not Recieve");

}

else

{

pBuf[iLen]=NULL;

strData=pBuf;

m_recieveddata.Insert(m_recieveddata.GetLength(),strData);

//display in server

UpdateData(FALSE);

m_sConnected.Send(pBuf,iLen); //send the data back to the Client

delete pBuf;

}

}

关闭连接

m_sConnected.ShutDown(0); 停止发送数据

m_sConnected.ShutDown(1); 停止接受数据

m_sConnected.ShutDown(2); 停止发送接受数据

m_sConnected.Close();

编写自己的socket类

在class view中选择添加一个新类,设置它的基类为CAsyncSocket,在类向导的帮助下添加如下的一些函数。

class MySocket : public CAsyncSocket

{ // Attributes

public:

// Operations

public:

MySocket();

virtual ~MySocket();

// Overrides

public:

void SetParentDlg(CDialog *pDlg);// ClassWizard generated virtual function overrides

//{{AFX_VIRTUAL(MySocket)

public:

virtual void OnAccept(int nErrorCode);

virtual void OnClose(int nErrorCode);

virtual void OnConnect(int nErrorCode);

virtual void OnOutOfBandData(int nErrorCode);

virtual void OnReceive(int nErrorCode);

virtual void OnSend(int nErrorCode);

//}}AFX_VIRTUAL // Generated message map functions

//{{AFX_MSG(MySocket)

// NOTE - the ClassWizard will add and remove member functions here. //}}AFX_MSG

protected:

private:

CDialog * m_pDlg;

};

设置“Parent Dialog”

调用这个socket类的SetParentDlg函数,保证当socket事件发生的时候这个窗体能接收到。

m_sListener.SetParentDlg(this);

m_sConnected.SetParentDlg(this);

建立Socket 事件和窗体成员函数之间的联系

在这个窗体类中添加一些函数,比如void OnReceive(); void OnClose(); void OnAccept(); void OnConnect()等,它们会在我们编写的的socket类中调用到。

void MySocket::OnAccept(int nErrorCode)

{

// TODO: Add your specialized code here and/or call the base class

if(nErrorCode==0)

{

((CServerDlg*)m_pDlg)-OnAccept();

}

CAsyncSocket::OnAccept(nErrorCode);

}

如何在WINDOWS环境下实现SOCKET编程

mfc只是对socket进行了一些封装,大部分人做网络编程都是用的原始的socket,比如如下接口都可以在c下进行调用

1.socket()

2.bind()

3.connect()

4.listen()

5.accept()

6.send() 和recv()

7.sendto() 和recvfrom()

8.close() 和shutdown()

9.getpeername()

10.gethostname()

这些接口是在Winsock2.h中定义的不是在mfc中定义的,你只需要包含Winsock2.h头文件和Ws2_32.lib库就可以了。

请问socket编程的开发环境包括什么?比如软件,语言等

C#可以进行socket编程的,推荐你看看这个

里面有英文网站的链接,使用的异步socket高效。

安装软件的话,建议你安装VS2012,语言的话C#

socket编程在windows和linux下的区别

下面大概分几个方面进行罗列:

Linux要包含

[cpp]

#include sys/socket.h

#include netinet/in.h

#include netdb.h

#include arpa/inet.h

等头文件,而windows下则是包含

[cpp]

#include winsock.h

Linux中socket为整形,Windows中为一个SOCKET。

Linux中关闭socket为close,Windows中为closesocket。

Linux中有变量socklen_t,Windows中直接为int。

因为linux中的socket与普通的fd一样,所以可以在TCP的socket中,发送与接收数据时,直接使用read和write。而windows只能使用recv和send。

设置socet选项,比如设置socket为非阻塞的。Linux下为

[cpp]

flag = fcntl (fd, F_GETFL);

fcntl (fd, F_SETFL, flag | O_NONBLOCK);

,Windows下为

[cpp]

flag = 1;

ioctlsocket (fd, FIONBIO, (unsigned long *) flag);

当非阻塞socket的TCP连接正在进行时,Linux的错误号为EINPROGRESS,Windows的错误号为WSAEWOULDBLOCK。

file

Linux下面,文件换行是"\n",而windows下面是"\r\n"。

Linux下面,目录分隔符是"/",而windows下面是"\"。

Linux与Windows下面,均可以使用stat调用来查询文件信息。但是,Linux只支持2G大小,而Windows只支持4G大小。为了支持更大的文件查询,可以在Linux环境下加

_FILE_OFFSET_BITS=64定义,在Windows下面使用_stat64调用,入参为struct __stat64。

Linux中可根据stat的st_mode判断文件类型,有S_ISREG、S_ISDIR等宏。Windows中没有,需要自己定义相应的宏,如

[cpp]

#define S_ISREG(m) (((m) 0170000) == (0100000))

#define S_ISDIR(m) (((m) 0170000) == (0040000))

Linux中删除文件是unlink,Windows中为DeleteFile。

time

Linux中,time_t结构是长整形。而windows中,time_t结构是64位的整形。如果要在windows始time_t为32位无符号整形,可以加宏定义,_USE_32BIT_TIME_T。

Linux中,sleep的单位为秒。Windows中,Sleep的单位为毫秒。即,Linux下sleep (1),在Windows环境下则需要Sleep (1000)。

Windows中的timecmp宏,不支持大于等于或者小于等于。

Windows中没有struct timeval结构的加减宏可以使用,需要手动定义:

[cpp]

#define MICROSECONDS (1000 * 1000)

#define timeradd(t1, t2, t3) do { \

(t3)-tv_sec = (t1)-tv_sec + (t2)-tv_sec; \

(t3)-tv_usec = (t1)-tv_usec + (t2)-tv_usec % MICROSECONDS; \

if ((t1)-tv_usec + (t2)-tv_usec MICROSECONDS) (t3)-tv_sec ++; \

} while (0)

#define timersub(t1, t2, t3) do { \

(t3)-tv_sec = (t1)-tv_sec - (t2)-tv_sec; \

(t3)-tv_usec = (t1)-tv_usec - (t2)-tv_usec; \

if ((t1)-tv_usec - (t2)-tv_usec 0) (t3)-tv_usec --, (t3)-tv_usec += MICROSECONDS; \

} while (0)

调用进程

Linux下可以直接使用system来调用外部程序。Windows最好使用WinExec,因为WinExec可以支持是打开还是隐藏程序窗口。用WinExec的第二个入参指明,如

SW_SHOW/SW_HIDE。

杂项

Linux为srandom和random函数,Windows为srand和rand函数。

Linux为snprintf,Windows为_snprintf。

同理,Linux中的strcasecmp,Windows为_stricmp。

错误处理

Linux下面,通常使用全局变量errno来表示函数执行的错误号。Windows下要使用GetLastError ()调用来取得。

Linux环境下仅有的

这些函数或者宏,Windows中完全没有,需要用户手动实现。

atoll

[cpp]

long long

atoll (const char *p)

{

int minus = 0;

long long value = 0;

if (*p == '-')

{

minus ++;

p ++;

}

while (*p = '0' *p = '9')

{

value *= 10;

value += *p - '0';

p ++;

}

return minus ? 0 - value : value;

}

gettimeofday

[cpp]

#if defined(_MSC_VER) || defined(_MSC_EXTENSIONS)

#define EPOCHFILETIME 11644473600000000Ui64

#else

#define EPOCHFILETIME 11644473600000000ULL

#endif

struct timezone

{

int tz_minuteswest;

int tz_dsttime;

};

int

gettimeofday (struct timeval *tv, struct timezone *tz)

{

FILETIME ft;

LARGE_INTEGER li;

__int64 t;

static int tzflag;

if (tv)

{

GetSystemTimeAsFileTime (ft);

li.LowPart = ft.dwLowDateTime;

li.HighPart = ft.dwHighDateTime;

t = li.QuadPart; /* In 100-nanosecond intervals */

t -= EPOCHFILETIME; /* Offset to the Epoch time */

t /= 10; /* In microseconds */

tv-tv_sec = (long) (t / 1000000);

tv-tv_usec = (long) (t % 1000000);

}

if (tz)

{

if (!tzflag)

{

_tzset ();

tzflag++;

}

tz-tz_minuteswest = _timezone / 60;

tz-tz_dsttime = _daylight;

}

return 0;

}

编译相关

当前函数,Linux用__FUNCTION__表示,Windows用__func__表示。

--------------------------------------------------------------------------------

Socket 编程 windows到Linux代码移植遇到的问题

1)头文件

windows下winsock.h/winsock2.h

linux下sys/socket.h

错误处理:errno.h

2)初始化

windows下需要用WSAStartup

linux下不需要

3)关闭socket

windows下closesocket(...)

linux下close(...)

4)类型

windows下SOCKET

linux下int

如我用到的一些宏:

#ifdef WIN32

typedef int socklen_t;

typedef int ssize_t;

#endif

#ifdef __LINUX__

typedef int SOCKET;

typedef unsigned char BYTE;

typedef unsigned long DWORD;

#define FALSE 0

#define SOCKET_ERROR (-1)

#endif

5)获取错误码

windows下getlasterror()/WSAGetLastError()

linux下errno变量

6)设置非阻塞

windows下ioctlsocket()

linux下fcntl() fcntl.h

7)send函数最后一个参数

windows下一般设置为0

linux下最好设置为MSG_NOSIGNAL,如果不设置,在发送出错后有可 能会导致程序退出。

8)毫秒级时间获取

windows下GetTickCount()

linux下gettimeofday()

3、多线程

多线程: (win)process.h --〉(linux)pthread.h

_beginthread -- pthread_create

_endthread -- pthread_exit

-----------------------------------------------------------------

windows与linux平台使用的socket均继承自Berkeley socket(rfc3493),他们都支持select I/O模型,均支持使用getaddrinfo与getnameinfo实现协议无关编程。但存在细微差别,

主要有:

头文件及类库。windows使用winsock2.h(需要在windows.h前包含),并要链接库ws2_32.lib;linux使用netinet/in.h, netdb.h等。

windows下在使用socket之前与之后要分别使用WSAStartup与WSAClean。

关闭socket,windows使用closesocket,linux使用close。

send*与recv*函数参数之socket长度的类型,windows为int,linux为socklen_t,可预编译指令中处理这一差异,当平台为windows时#define socklen_t unsigned int。

select函数第一个参数,windows忽略该参数,linux下该参数表示集合中socket的上限值,一般设为sockfd(需select的socket) + 1。

windows下socket函数返回值类型为SOCKET(unsigned int),其中发生错误时返回INVALID_SOCKET(0),linux下socket函数返回值类型int, 发生错误时返回-1。

另外,如果绑定本机回环地址,windows下sendto函数可以通过,linux下sendto回报错:errno=22, Invalid arguement。一般情况下均绑定通配地址。

转载jlins

(责任编辑:IT教学网)

更多

推荐金山WPS文章