代码来源于 》》》》》》》》》》》》》》》》》》》》》 Windows Sockets网络开发VC++ 这本书
在stdafx.h 中添加 #pragma comment(lib,"ws2_32.lib")
服务端 程序
// server.cpp : 定义控制台应用程序的入口点。
//
#include "stdafx.h"
#include "winsock2.h"
int _tmain(int argc, _TCHAR* argv[])
{
printf("Server\n");
//******************************************创建套接字
WSADATA wsd; //WSADATA 变量
SOCKET sServer; //服务器套接字
int retVal;//返回值
/*
int WSAStartup(
WORD wVersionRequested, //指定准备加载Windows Sockets 动态库的版本
LPWSADATA lpWSAData ) //指向LPWSADATA 结构的指针,该参数返回被加载动态库的有关信息
该函数使得应用程序和Windows Sockets DLL之间能够互相通知对方可以支持的最高版本以及相互确认对方的版本是否可以接受
return :wsaData将输出参数的wVersion值 ,指示了应用程序将使用的最终版本
WORD MAKEWORD(
BYTE bLow, //指定新变量的低字节序;
BYTE bHigh //指定新变量的高字节序;
);
return :一个无符号16位整形数.
*/
//初始化套接字动态库
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
{
printf("WSAStartup failed!\n");
return 1;
}
/*
SCOKET socket(
int af, //协议的地址家族。创建TCP或者UDP套接字时,该参数为AF——INET
int type, //协议的套接字类型。 有 SOCK_STREAM,SOCK_DGRAM、SOCK_RAM类型
int protocol) //协议。SOCK_STREAM 该字段为IPPROTO_TCP 或者为0; SOCK_DGRAM 该字段为IPPROTO_UDP 或者为0
return:成功:返回一个新建的套接字句柄
失败:返回INVALID_SOCKET。
*/
//创建套接字
sServer = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sServer)
{
printf("socket failed!\n");
WSACleanup(); //释放套接字资源;
return -1;
}
//******************************************绑定套接字
/*
* Socket address, internet style.
SOCKADDR_IN
struct sockaddr_in {
short sin_family;
u_short sin_port;
struct in_addr sin_addr;
char sin_zero[8];
};
*/
SOCKADDR_IN addrServ; //服务器地址
char optval = -1;
int optlen = -1;
setsockopt(sServer, SOL_SOCKET, SO_REUSEADDR, &optval, optlen);
//服务器套接字地址
addrServ.sin_family = AF_INET;
addrServ.sin_port = htons(4999);
addrServ.sin_addr.s_addr = INADDR_ANY;
/*
int bind(
SOCKET s, //套接字
const struct sockaddr FAR* name,//地址
int namelen //sockaddr结构长度
)
return:成功 :0
失败 :SOCKET_ERROR
*/
//绑定套接字
retVal = bind(sServer, (LPSOCKADDR)&addrServ, sizeof(SOCKADDR_IN));
if (SOCKET_ERROR == retVal)
{
printf("server bind failed !\n");
closesocket(sServer); //关闭套接字
WSACleanup(); //释放套接字资源
return -1;
}
//******************************************监听
/*
int listen(
SOCKET s, //套接字
int backlog //指定等待连续的最大队列长度
)
return : 成功:0 失败:SOCKET_ERROR
*/
//开始监听
retVal = listen(sServer, 1);
if (SOCKET_ERROR == retVal)
{
printf("listen failed!\n");
closesocket(sServer); //关闭套接字
WSACleanup(); //释放套接字资源
return -1;
}
//******************************************接受客户端连接
/*
SOCKET accept(
SOCKET s, //监听套接字
struct sockaddr FAR* addr, //该参数返回请求连接主机的地址
int FAR* addrlen //该参数返回SOCKADDR_IN结构的长度
)
return :
成功:主机接受了等待队列中的第一个请求。
addr结构返回发起请求的客户端的地址,addrlen参数指出了地址结构的长度
返回一个新的套接字句柄。服务器使用该套机字与客户端进行数据传输。而监听套接字任然用于接受客户端的连接
失败:INVALID_SOCKET错误
*/
//接受客户端请求
sockaddr_in addrClient;
SOCKET sClient;
int addrClientlen = sizeof(addrClient);
sClient = accept(sServer, (sockaddr FAR*)&addrClient, &addrClientlen);
if (INVALID_SOCKET == sClient)
{
printf("accept failed!\n");
closesocket(sServer);//关闭套接字
WSACleanup(); //释放套接字资源
return -1;
}
//******************************************接受并显示数据
/*
int recv(
SOCKET s, //套接字
char FAR* buf, //接收数据缓冲区
int len, //缓冲区的长度
int flags 0代表无特殊行为;MSG_PEEK 代表 会使有用的数据被复制到接收缓冲区内,但没有从系统缓冲区将其删除;
MSG_OOB 表示处理带外数据
)
return: 成功:为接受的字节数
失败:SOCKET_ERROR
*/
//接收客户端数据
char buf[128];
int BUF_SZIE = 128;
ZeroMemory(buf,BUF_SZIE); //设置接收数据缓冲区为0
retVal = recv(sClient, buf, BUF_SZIE, 0);
if (SOCKET_ERROR == retVal)
{
printf("recv failed!\n");
closesocket(sServer); //关闭套接字
closesocket(sClient); // 关闭套接字
WSACleanup(); //释放套接字资源
return -1;
}
printf("%s\n", buf);// 输出“MYTCP”
//******************************************退出
closesocket(sServer); //关闭套接字
closesocket(sClient); //关闭套接字
WSACleanup(); //释放套接字资源
return 0;
}
客户端代码
// client.cpp : 客户端实现
//
#include "stdafx.h"
#include "winsock2.h"
#define BUF_SZIE 64 //缓冲区大小
int _tmain(int argc, _TCHAR* argv[])
{
printf("Client\n");
//******************************************创建套接字
WSADATA wsd; //WSADATA 变量
SOCKET sHost; // 服务器套接字
SOCKADDR_IN servAddr; //服务器地址
char buf[BUF_SZIE]; //接收数据缓冲区
int retVal; //返回值
//初始化套接字动态库
if (WSAStartup(MAKEWORD(2, 2), &wsd) != 0)
{
printf("WSAStartup failed!\n");
return -1;
}
//创建套接字
sHost = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sHost)
{
printf("socket failed!\n");
WSACleanup();
return -1;
}
//******************************************连接服务器
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servAddr.sin_port = htons((short)4999);
int nServAddlen = sizeof(servAddr);
//连接服务器
retVal = connect(sHost, (LPSOCKADDR)&servAddr, sizeof(servAddr));
if (SOCKET_ERROR == retVal)
{
printf("connect failed!\n");
closesocket(sHost); //关闭套接字
WSACleanup(); //释放套接字
return -1;
}
//******************************************发送数据
/*
int send(
SOCKET s, //套接字
const char FAR* buf, //发送数据缓冲区
int len, //发送数据长度
int flags // 0代表无特殊行为;MSG_DONTROUTE 标志要求传输层不要将数据路由出去
MSG_OOB 表示该数据应该被带外发送
)
return: 成功:为实际发送的字节数
失败:SOCKET_ERROR
*/
//向服务器发送数据
ZeroMemory(buf, BUF_SZIE);
strcpy_s(buf, "MyFirstTCP");
retVal = send(sHost, buf, strlen(buf), 0);
if (SOCKET_ERROR == retVal)
{
printf("send failed!\n");
closesocket(sHost);
WSACleanup();
return -1;
}
//*****************************************退出
closesocket(sHost);
WSACleanup();
return 0;
}
先打开server 后打开client
效果图