客户端
#include"stdafx.h"
#define WIN32_LEAN_AND_MEAN
#include<Windows.h>
#include<WinSock2.h>
#include<WS2tcpip.h>
#include<stdlib.h>
#include<stdio.h>
//连接到winsock2对应的lib文件:ws2_32.lib,Mswsock.lib,Advapi32.lib
#pragma comment (lib,"Ws2_32.lib")
#pragma comment (lib,"Mswsock.lib")
#pragma comment (lib,"AdvApi32.lib")
//定义默认的缓冲区长度和端口号
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
int _cdecl main(int argc, char** argv)
{
WSADATA wsadata;
SOCKET Connectsocket = INVALID_SOCKET;
struct addrinfo * result = NULL,*ptr = NULL,hints;
char *sendbuf = "bryant_xw";
char recvbuf[DEFAULT_BUFLEN];
int iResult;
int recvbuflen = DEFAULT_BUFLEN;
//验证参数的合法性
if(argc != 2)
{
printf("usage:%s server-name\n",argv[0]);
return 1;
}
//初始化套接字
iResult = WSAStartup(MAKEWORD(2,2),&wsadata);
if(iResult != 0)
{
printf("WSAStartup failed with error %d\n",iResult);
return 1;
}
ZeroMemory(&hints,sizeof(hints));
hints.ai_family = AF_UNSPEC;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
//解析服务器的地址和端口
iResult = getaddrinfo(argv[1],DEFAULT_PORT,&hints,&result); //成功返回的是0
if(iResult != 0)
{
printf("GetAddrInfo is failed with error %d\n",iResult);
WSACleanup();
return 1;
}
//尝试连接服务器地址,直到成功
for(ptr = result; ptr!=NULL;ptr = ptr->ai_next)
{
//创建套接字
Connectsocket = socket(ptr->ai_family,ptr->ai_socktype,ptr->ai_protocol);
if(Connectsocket == INVALID_SOCKET)
{
printf("socket failed with error %ld\n",WSAGetLastError());
WSACleanup();
return 1;
}
//向服务器发起连接
iResult = connect(Connectsocket,ptr->ai_addr,(int)ptr->ai_addrlen);
if(iResult == SOCKET_ERROR)
{
closesocket(Connectsocket);
Connectsocket = INVALID_SOCKET;
continue;
}
break;
}
freeaddrinfo(result);
if(Connectsocket == INVALID_SOCKET)
{
printf("unable to connect to server");
WSACleanup();
return 1;
}
//发送缓冲区的测试数据
iResult = send(Connectsocket,sendbuf,(int)strlen(sendbuf),0);
if(iResult == SOCKET_ERROR)
{
printf("send failed with error %ld\n",WSAGetLastError());
closesocket(Connectsocket);
WSACleanup();
return 1;
}
printf("Bytes sent :%ld\n",iResult);
//数据发送结束,调用shutdown函数声明不再发送数据,但是此时客户端人可以接收数据
iResult = shutdown(Connectsocket,SD_SEND);
if(iResult == SOCKET_ERROR)
{
printf("shutdown failed with error %ld\n",WSAGetLastError());
closesocket(Connectsocket);
WSACleanup();
return 1;
}
//持续接收数据,直到服务器关闭连接
do
{
iResult = recv(Connectsocket,recvbuf,recvbuflen,0);
if(iResult > 0)
printf("Bytes recevied: %d\n",iResult);
else if(iResult == 0)
printf("Connection closed\n");
else
printf("recv failed with error: %d\n",WSAGetLastError());
} while (iResult > 0);
//关闭套接字
closesocket(Connectsocket);
//释放资源
WSACleanup();
return 0;
}
服务器端
#include"stdafx.h"
#undef UNICODE
#define WIN32_LEAN_AND_MEAN
#include<Windows.h>
#include<WinSock2.h>
#include<WS2tcpip.h>
#include<stdlib.h>
#include<stdio.h>
#pragma comment(lib,"Ws2_32.lib")//连接到Winsock 2 对应的lib文件:ws2_32.lib
//定义默认的缓冲区长度和端口号
#define DEFAULT_BUFLEN 512
#define DEFAULT_PORT "27015"
int _cdecl main(void)
{
WSADATA wsadata;
int iResult;
SOCKET ListenSocket = INVALID_SOCKET;
SOCKET ClientSocket = INVALID_SOCKET;
struct addrinfo *result = NULL;
struct addrinfo hints;
int iSentResult;
char recvbuf[DEFAULT_BUFLEN];
int recvbuflen = DEFAULT_BUFLEN;
//初始化winsock
iResult = WSAStartup(MAKEWORD(2,2),&wsadata);
if(iResult != 0)
{
printf("WSAStartup failed with error:%d\n",iResult);
return 1;
}
ZeroMemory(&hints,sizeof(hints));
//声明IPv4地址族,流式套接字,TCP协议
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_STREAM;
hints.ai_protocol = IPPROTO_TCP;
hints.ai_flags = AI_PASSIVE;
//解析服务器地址和端口号
iResult = getaddrinfo(NULL,DEFAULT_PORT,&hints,&result); //成功返回的是0
if(iResult != 0)
{
printf("getaddrinfo is failed with error %d\n",iResult);
return 1;
}
//调用socket函数创建一个流式套接字
ListenSocket = socket(result->ai_family,result->ai_socktype,result->ai_protocol);
if(ListenSocket == INVALID_SOCKET)
{
printf("socket failed with error %ld\n",WSAGetLastError());
free(result);
WSACleanup();
return 1;
}
//为套接字绑定地址和端口号
iResult = bind(ListenSocket,result->ai_addr,(int)result->ai_addrlen); //成功返回0
if(iResult != 0)
{
printf("bind failed with error %d\n",WSAGetLastError());
freeaddrinfo(result);
closesocket(ListenSocket);
WSACleanup();
return 1;
}
freeaddrinfo(result);
//监听连接请求
iResult = listen(ListenSocket,SOMAXCONN);//成功返回0
if(iResult != 0)
{
printf("listen failed with error %d\n",WSAGetLastError()); //
closesocket(ListenSocket);
WSACleanup();
return 1;
}
//接收客户端的连接请求,返回 新的 连接套接字 ClientSocket ,之后在ClientSocket上读写
ClientSocket = accept(ListenSocket,NULL,NULL);
if(ClientSocket == INVALID_SOCKET)
{
printf("accept failed with error %d\n",WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
//持续接收数据直到对方关链接
do
{
iResult = recv(ClientSocket,recvbuf,recvbuflen,0);
//case 1:成功接收数据
if(iResult > 0)
{
printf("Bytes received:%d\n",iResult);
//将缓冲区的内容回送给客户端
iSentResult = send(ClientSocket,recvbuf,iResult,0);
if(iSentResult == SOCKET_ERROR)
{
printf("send failed with error %d\n",WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
printf("Bytes sent: %d\n",iSentResult);
}
//case 2: 连接关闭
else if(iResult == 0)
{
printf("Connection closing..\n");
}
//case3: 接收发生错误
else
{
printf("recv failed with error %d\n",WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
} while (iResult > 0);
//关闭连接
iResult = shutdown(ClientSocket,SD_SEND);
if(iResult != 0)
{
printf("shutdown failed with error %d\n",WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//关闭套接字,释放资源
closesocket(ClientSocket);
WSACleanup();
//在必须要监听的套接字的情况下释放该套接字
closesocket(ListenSocket);
return 0;
}
运行的结果如下图: