孙鑫MFC(14)--网络编程

本文介绍了MFC中的网络编程,包括套接字(socket)的基本概念、网络字节顺序、客户机/服务器模式等,并通过示例详细讲解了面向连接和无连接的网络通信编程方法。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

孙鑫MFC(14)--网络编程

//-----------网络编程-----------------

//--------------服务器程序-------------

//所要包含的库文件

#include <Winsock2.h>

#include <stdio.h>

//需要在工程设置链接库中添加ws2_32.lib

1、套接字(socket)

//由美国伯克利大学在Unix上推出了一种应用程序访问通信协议的操作系统调用SOCKET,从而使程序员可以很方便地访问TCP/IP,开发出各种网络应用程序。

2、网络字节顺序

//不同的计算机存放多字节值的顺序不同,有是高位先存,有的低位先存

//在网络协议中需要制定网络字节顺序, TCP/IP协议使用16位整数和32位整数的高位先存格式

3、客户机/服务器模式

Client/Server

基于客户机/服务器模式的TCP/IP

2009年12月3日 - Fly - 飛

4、Windows Sockets 的实现

从Berkeley Sockets扩展而来,对他进行了重要扩充,提供了一些异步函数,增加了符合消息驱动特性的网络事件异步选择机制。

三种套接字的类型

2009年12月3日 - Fly - 飛

有链接及无连接的 Socket编程

2009年12月3日 - Fly - 飛2009年12月3日 - Fly - 飛

二、示例

//---------------面向有链接的网络通信--------------------

1、加载套接字库

WSAStartup() //加载套接字库,并进行套接字库的版本协商(确定使用哪个版本的套接字库)

2009年12月3日 - Fly - 飛

//下面代码来自帮助,演示了如何使用1.1版 的WinSock库

WORD wVersionRequested;

WSADATA wsaData;

int err;

wVersionRequested = MAKEWORD( 1, 1 );

//相当于wVersionRequested = 0x101;

err = WSAStartup( wVersionRequested, &wsaData );

if ( err != 0 ) {

/* Tell the user that we could not find a usable */

/* WinSock DLL. */

//printf("找不到winsock.dll/n");

return;

}

/* Confirm that the WinSock DLL supports 1.1.*/

/* Note that if the DLL supports versions greater */

/* than 1.1 in addition to 1.1, it will still return */

/* 1.1 in wVersion since that is the version we */

/* requested. */

if ( LOBYTE( wsaData.wVersion ) != 1 ||

HIBYTE( wsaData.wVersion ) != 1 ) {

/* Tell the user that we could not find a usable */

/* WinSock DLL. */

WSACleanup( );

return;

}

/* The WinSock DLL is acceptable. Proceed. */

//-----------------------------------------------------

SOCKET sockSrv = socket(AF_INET,SOCK_STREAM,0);

//对于TCP/IP协议的套接字,只能用AF_INET(PF_INET)地址族

//SOCK_STREAM基于TCP协议的套接字

//0为自动选择协议

if(scokSrv == SOCKET_ERROR)

{

printf("创建Sockets出错/n");

WSACleanup();

return;

}

SOCKADDR_IN addrSrv; //定义地址结构

addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY); //表示自动接收并发给任何地址

//htonl()函数表示转为网络字节序

addrSrv.sin_family = AF_INET; //指定地址族

addrSrv.sin_port = htons(6000); //指定端口号

//绑定本地地址及端口号

bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

listen(sockSrv,5) //监听,等待链接的最大数为5

SOCKADDR_IN addrClinet; //用于接收客户端套接字

int len = sizeof(SOCKADDR);

while(1)

{

//accept()函数,用于接受客户端发来的信息,并新创建一个符合客户端的套接字作为返回值

SOCKET sockConn = accept(sockSrv,(SOCKADDR*)&addrClinet,&len);

char sendBuf[100];

//将字符串信息格式化到发送缓存中

sprintf(sendBuf,"Welcome %s to my home",inet_ntoa(addrClinet.sin_addr));

//inet_ntoa()函数表示将in_addr结构体转为网络字节格式

send(sockConn,sendBuf,strlen(sendBuf) + 1,0);

//采用新建的套接字进行传送,加1是为了给发给客户端的信息加上'/0'介绍符

//最后个参数默认为0

char recvBuf[100];

int iRect;

//接收客户端信息

iRect = recv(sockConn,recvBuf,100,0);

recvBuf[iRect] = '/0';

//打印信息

printf("%s/n",recvBuf);

//关闭套接字

closesocket(sockConn);

}

//----------------------------------------------------

//==============客户端代码============

WORD wVersionRequested;

WSADATA wsaData;

int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );

if ( err != 0 ) {

/* Tell the user that we could not find a usable */

/* WinSock DLL. */

return;

}

/* Confirm that the WinSock DLL supports 1.1.*/

/* Note that if the DLL supports versions greater */

/* than 1.1 in addition to 1.1, it will still return */

/* 1.1 in wVersion since that is the version we */

/* requested. */

if ( LOBYTE( wsaData.wVersion ) != 1 ||

HIBYTE( wsaData.wVersion ) != 1 ) {

/* Tell the user that we could not find a usable */

/* WinSock DLL. */

WSACleanup( );

return;

}

/* The WinSock DLL is acceptable. Proceed. */

//---------------------------------

SOCKET sockClient = socket(AF_INET,SOCK_STREAM,0);

if(scokClient == SOCKET_ERROR)

{

printf("创建Sockets出错/n");

WSACleanup();

return;

}

SOCKADDR_IN addrSrv;

addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

addrSrv.sin_family = AF_INET;

addrSrv.sin_port = htons(6000);

if(SOCKET_ERROR == connect(sockClient,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR)))

{

printf("链接服务器出错/n");

WSACleanup();

return;

}

/*

int iRect;

//接收客户端信息

iRect = recv(sockConn,recvBuf,100,0);

recvBuf[iRect] = '/0';

这一行代码不可少!因为recv函数不会自动将数据缓冲末尾

设为表示数据结束的空中止符(`/0`),因此,一不留神就会出现缓冲区越界。

当然也可以在调用recv函数前先将缓冲区清0(用ZeroMemory或memset),不过

还是建议加上这一句。*/

char recvBuf[100];

recv(sockConn,recvBuf,100,0);

printf("%s/n",recvBuf);

send(sockClient,"This is lisi",strlen("This is lisi") + 1,0);

closesocket(sockClient);

WSACleanup();

//-------------------------------------------------------------------------

//===========面向无连接的通信============

//--------服务器端---------------

WORD wVersionRequested;

WSADATA wsaData;

int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );

if ( err != 0 ) {

/* Tell the user that we could not find a usable */

/* WinSock DLL. */

return;

}

/* Confirm that the WinSock DLL supports 1.1.*/

/* Note that if the DLL supports versions greater */

/* than 1.1 in addition to 1.1, it will still return */

/* 1.1 in wVersion since that is the version we */

/* requested. */

if ( LOBYTE( wsaData.wVersion ) != 1 ||

HIBYTE( wsaData.wVersion ) != 1 ) {

/* Tell the user that we could not find a usable */

/* WinSock DLL. */

WSACleanup( );

return;

}

/* The WinSock DLL is acceptable. Proceed. */

//----------------------------------------------------------------

//无需循环监听,无需接受并单独创建套接字

SOCKET sockSrv = socket(AF_INET,SOCK_DGRAM,0);

SOCKADDR_IN addrSrv;

addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);

addrSrv.sin_family = AF_INET;

addrSrv.sin_port = htons(6000);

bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

SOCKADDR_IN addrClient;

int len = sizeof(SOCKADDR);

char recvBuf[100];

recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len);

printf("%s/n",recvBuf);

closesocket(sockSrv);

WSACleanup();

//------------------------客户端-----------------------------

#include <winsock2.h>

#include <stdio.h>

#pragma comment(lib,"ws2_32.lib");

void main()

{

WORD wVersionRequested;

WSADATA wsaData;

int err;

wVersionRequested = MAKEWORD( 1, 1 );

//相当于wVersionRequested = 0x101;

err = WSAStartup( wVersionRequested, &wsaData );

if ( err != 0 ) {

/* Tell the user that we could not find a usable */

/* WinSock DLL. */

//printf("找不到winsock.dll/n");

return;

}

/* Confirm that the WinSock DLL supports 1.1.*/

/* Note that if the DLL supports versions greater */

/* than 1.1 in addition to 1.1, it will still return */

/* 1.1 in wVersion since that is the version we */

/* requested. */

if ( LOBYTE( wsaData.wVersion ) != 1 ||

HIBYTE( wsaData.wVersion ) != 1 ) {

/* Tell the user that we could not find a usable */

/* WinSock DLL. */

WSACleanup( );

return;

}

/* The WinSock DLL is acceptable. Proceed. */

SOCKET sockClient = socket(AF_INET,SOCK_DGRAM,0);

SOCKADDR_IN addrSrv;

addrSrv.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");

addrSrv.sin_family = AF_INET;

addrSrv.sin_port = htons(6000);

sendto(sockClient,"Hello",strlen("Hello")+1,0,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

closesocket(sockClient);

WSACleanup();

}

//---------------------------------------------


以上转自:http://mxmkeep.blog.163.com/blog/

====================================================================================

1.加载套接字库
2.WSAStartup
The Windows Sockets WSAStartup function initiates use of Ws2_32.dll by a process.

int WSAStartup(
WORD wVersionRequested,
LPWSADATA lpWSAData
);

typedef struct WSAData {
WORD wVersion;
WORD wHighVersion;
char szDescription[WSADESCRIPTION_LEN+1];
char szSystemStatus[WSASYS_STATUS_LEN+1];
unsigned short iMaxSockets;
unsigned short iMaxUdpDg;
char FAR * lpVendorInfo;
} WSADATA, *LPWSADATA;

socket
The Windows Sockets socket function creates a socket that is bound to a specific service provider.

SOCKET socket(
int af,
int type,
int protocol
);

int bind(
SOCKET s,
const struct sockaddr FAR *name,
int namelen
);

struct sockaddr_in{
short sin_family;
unsigned short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};

Vc++6.0 error LNK2005: _main already defined in UdpClient.obj UDP时出现的问题

/**************************************************服务器端************************************************/

#include <Winsock2.h>
#include <stdio.h>

void main()
{
//加载套接字库,套接字库的版本协商 WSAStartup
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return;
}

if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
{
WSACleanup( );//终止套接字库的使用
return;
}

SOCKET sockSrv = socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr = htonl(INADDR_ANY);
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);

bind(sockSrv,(SOCKADDR*)&addrSrv,sizeof(SOCKADDR));

char recvBuf[100];
char sentBuf[100];
char tempBuf[200];

SOCKADDR_IN addrClient;
int len = sizeof(SOCKADDR); //返回地址结构的长度

while (1)
{
recvfrom(sockSrv,recvBuf,100,0,(SOCKADDR*)&addrClient,&len); //接收地址(SOCKADDR*)&addrClient
if ('q'==recvBuf[0])
{
sendto(sockSrv,"q",strlen("q")+1,0,(SOCKADDR*)&addrClient,len); //发送地址
printf("Chat end!/n");
break;
}
sprintf(tempBuf,"%s say : %s",inet_ntoa(addrClient.sin_addr),recvBuf);//对方的IP地址addrClient.sin_addr
printf("%s/n",tempBuf);

printf("Please input data:/n");
gets(sentBuf);//从键盘上获取输入流
sendto(sockSrv,sentBuf,strlen(sentBuf)+1,0,(SOCKADDR*)&addrClient,len);

}
closesocket(sockSrv); //关闭套接字
WSACleanup(); //终止对套接字库的使用
}

/**************************************************客户端端************************************************/

#include <Winsock2.h>
#include <stdio.h>

void main()
{
//加载套接字库,套接字库的版本协商 WSAStartup
WORD wVersionRequested;
WSADATA wsaData;
int err;

wVersionRequested = MAKEWORD( 1, 1 );

err = WSAStartup( wVersionRequested, &wsaData );
if ( err != 0 )
{
return;
}

if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 )
{
WSACleanup( );//终止套接字库的使用
return;
}

SOCKET sockClient = socket(AF_INET,SOCK_DGRAM,0);
SOCKADDR_IN addrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");
addrSrv.sin_family = AF_INET;
addrSrv.sin_port = htons(6000);

char recvBuf[100];
char sentBuf[100];
char tempBuf[200];

int len = sizeof(SOCKADDR); //返回地址结构的长度

while (1)
{
printf("Please input data:/n");
gets(sentBuf);//从键盘上获取输入流
sendto(sockClient,sentBuf,strlen(sentBuf)+1,0,(SOCKADDR*)&addrSrv,len);

recvfrom(sockClient,recvBuf,100,0,(SOCKADDR*)&addrSrv,&len);
if ('q'==recvBuf[0])
{
sendto(sockClient,"q",strlen("q")+1,0,(SOCKADDR*)&addrSrv,len);
printf("Chat end!/n");
break;
}
sprintf(tempBuf,"%s say : %s",inet_ntoa(addrSrv.sin_addr),recvBuf);
printf("%s/n",tempBuf);

}
closesocket(sockClient);
WSACleanup();
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值