因为我的毕业设计要用到网络,一开始我就打算做 IOCP Server,我想用最好的方法去实现,结果发现啃不动,于是就从这个示例程序开始吧!
客户端代码:
/*
* 文件:简单示例(客户端)
* 说明:项目中需包含 Ws2_32.lib,或使用 #pragma once
*/
#include <stdio.h>
#include <WinSock2.h>
#define LENGTH 128
#define PORT_NUM 8086
#define EXIT_WITH_MESSAGE(content) \
do \
{ \
WSACleanup(); \
printf_s(content); \
system("pause"); \
return EXIT_FAILURE; \
} \
while (FALSE);
int main()
{
int ret, len;
WORD wVersion; // 网络传输版本
WSADATA wsaData; // WSADATA
char msg[LENGTH];
struct sockaddr_in server; // 服务器信息
SOCKET sockClient = INVALID_SOCKET; // 待创建的套接字
wVersion = MAKEWORD(2, 2);
ret = WSAStartup(wVersion, &wsaData); // 初始化 WinSock DLL
if (ret != 0)
{
// 告诉用户不能获取可用的 WinSock DLL
EXIT_WITH_MESSAGE("WSAStartup Failed, cannot find a usable winsock dll!\n");
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
// 告诉用户版本不正确
EXIT_WITH_MESSAGE("Error version!\n");
}
sockClient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sockClient)
{
// 套接字创建失败
EXIT_WITH_MESSAGE("Invalid socket!\n");
}
server.sin_family = AF_INET;
server.sin_port = htons(PORT_NUM);
server.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
ret = connect(sockClient, (struct sockaddr *)&server, sizeof(struct sockaddr));
if (SOCKET_ERROR == ret)
{
// 连接失败
closesocket(sockClient);
EXIT_WITH_MESSAGE("Connect failed!\n");
}
do
{
printf_s("Input a message to send (Note: Length < 128): ");
gets_s(msg, LENGTH);
// send 函数将会把消息发送到已连接的套接字上,而 sendto 则是发送到指定套接字上
len = strlen(msg) + 1;
ret = send(sockClient, msg, len, 0);
if (ret < 0 || ret > len)
{
// 发送有误
closesocket(sockClient);
EXIT_WITH_MESSAGE("Send message error!\n");
}
if (strcmp(msg, "Quit") == 0)
break;
memset(msg, 0, LENGTH);
ret = recv(sockClient, msg, LENGTH, 0);
if (SOCKET_ERROR == ret)
{
// 接受有误
closesocket(sockClient);
EXIT_WITH_MESSAGE("Receive message error!\n");
}
else if (0 == ret)
{
// 连接断开
closesocket(sockClient);
EXIT_WITH_MESSAGE("The connection closed!\n");
}
printf_s("Client reply: %s\n", msg);
}
while (strcmp(msg, "Quit"));
printf_s("Exit connection!\n");
closesocket(sockClient);
WSACleanup();
system("pause");
return EXIT_SUCCESS;
}
服务器端代码:
/*
* 文件:简单示例(服务器端)
* 说明:项目中需包含 Ws2_32.lib,或使用 #pragma once
*/
#include <stdio.h>
#include <WinSock2.h>
#define LENGTH 128
#define PORT_NUM 8086
#define EXIT_WITH_MESSAGE(content) \
do \
{ \
WSACleanup(); \
printf_s(content); \
system("pause"); \
return EXIT_FAILURE; \
} \
while (FALSE);
int main()
{
int ret, len;
WORD wVersion; // 网络传输版本
WSADATA wsaData; // WSADATA
char msg[LENGTH];
struct sockaddr_in server, client; // 服务器信息,客户端信息
SOCKET sockServer = INVALID_SOCKET, sockListener = INVALID_SOCKET; // 服务器套接字,监听套接字
wVersion = MAKEWORD(2, 2);
ret = WSAStartup(wVersion, &wsaData); // 初始化 WinSock DLL
if (ret != 0)
{
// 告诉用户不能获取可用的 WinSock DLL
EXIT_WITH_MESSAGE("WSAStartup Failed, cannot find a usable winsock dll!\n");
}
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
// 告诉用户版本不正确
EXIT_WITH_MESSAGE("Error version!\n");
}
sockListener = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (INVALID_SOCKET == sockListener)
{
// 套接字创建失败
EXIT_WITH_MESSAGE("Invalid listener socket!\n");
}
server.sin_family = AF_INET;
server.sin_addr.s_addr = INADDR_ANY;
server.sin_port = htons(PORT_NUM);
ret = bind(sockListener, (struct sockaddr *)&server, sizeof(struct sockaddr_in));
if (SOCKET_ERROR == ret)
{
// 绑定端口失败
closesocket(sockListener);
EXIT_WITH_MESSAGE("Bind error!\n");
}
ret = listen(sockListener, SOMAXCONN);
if (SOCKET_ERROR == ret)
{
// 监听失败
closesocket(sockListener);
EXIT_WITH_MESSAGE("Listen error!\n");
}
len = sizeof(struct sockaddr_in);
sockServer = accept(sockListener, (struct sockaddr*)&client, &len);
if (INVALID_SOCKET == sockServer)
{
// 接收失败
closesocket(sockListener);
EXIT_WITH_MESSAGE("Accept error!\n");
}
do
{
memset(msg, 0, LENGTH);
ret = recv(sockServer, msg, LENGTH, 0);
if (SOCKET_ERROR == ret)
{
// 接受有误
closesocket(sockServer);
EXIT_WITH_MESSAGE("Receive message error!\n");
}
else if (0 == ret)
{
// 连接断开
closesocket(sockServer);
EXIT_WITH_MESSAGE("The connection closed!\n");
}
printf_s("Client: %s\n", msg);
strcpy_s(msg, LENGTH, "SweetLover has received your letter, he'll reply soon!");
len = strlen(msg) + 1;
ret = send(sockServer, msg, len, 0);
if (ret <= 0 || ret > len)
{
// 发送有误
closesocket(sockServer);
EXIT_WITH_MESSAGE("Send message error!\n");
}
}
while (TRUE);
printf_s("Exit connection!\n");
closesocket(sockServer);
closesocket(sockListener);
WSACleanup();
system("pause");
return EXIT_SUCCESS;
}
总结:
1.网络连接的步骤:http://blog.csdn.net/wwqingyue/article/details/8792608
UDP和TCP编程步骤也有些不同,如下:
TCP编程的服务器端一般步骤是:
1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt(); * 可选 3、绑定IP地址、端口等信息到socket上,用函数bind(); 4、开启监听,用函数listen(); 5、接收客户端上来的连接,用函数accept(); 6、收发数据,用函数send()和recv(),或者read()和write(); 7、关闭网络连接; 8、关闭监听;
TCP编程的客户端一般步骤是:
1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();* 可选 3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 4、设置要连接的对方的IP地址和端口等属性; 5、连接服务器,用函数connect(); 6、收发数据,用函数send()和recv(),或者read()和write(); 7、关闭网络连接;
与之对应的UDP编程步骤要简单许多,分别如下:
UDP编程的服务器端一般步骤是:
1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();* 可选 3、绑定IP地址、端口等信息到socket上,用函数bind(); 4、循环接收数据,用函数recvfrom(); 5、关闭网络连接;
UDP编程的客户端一般步骤是:
1、创建一个socket,用函数socket(); 2、设置socket属性,用函数setsockopt();* 可选 3、绑定IP地址、端口等信息到socket上,用函数bind();* 可选 4、设置对方的IP地址和端口等属性; 5、发送数据,用函数sendto(); 6、关闭网络连接;
2.套接字编程原理:http://www.cnblogs.com/haoyuanyuan/p/3268351.html
3.常用术语概念:http://www.vckbase.com/index.php/wv/300