孙鑫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
4、Windows Sockets 的实现
从Berkeley Sockets扩展而来,对他进行了重要扩充,提供了一些异步函数,增加了符合消息驱动特性的网络事件异步选择机制。
三种套接字的类型
有链接及无连接的 Socket编程
二、示例
//---------------面向有链接的网络通信--------------------
1、加载套接字库
WSAStartup() //加载套接字库,并进行套接字库的版本协商(确定使用哪个版本的套接字库)
//下面代码来自帮助,演示了如何使用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();
}