1、基于TCP的socket编程的服务器-客户端流程
服务器端流程:加载套接字库WSAStartup()—>创建套接字socket()—>将套接字绑定到本地地址和端口上bind()—>将套接字设置为监听模式listen()—>循环等待、接收连接的到来accept()—>用accept返回的套接字和客户端进行通信recv()/send(),通信结束后关闭通信套接字closesocket()—>服务器关闭时关闭监听套接字closesocket()—>结束套接字库的使用WSACleanup()。
代码示例:
#include <stdio.h>
#include <Winsock2.h>
#include <process.h>
#include <Ws2tcpip.h>
#pragma comment(lib,"Ws2_32.lib")
#define DEFAULT_BUFLEN 512
unsigned _stdcall Thread1Fun(void* lpParameter)
{
SOCKET ConnectSocket = (SOCKET)lpParameter;
//向客户端发送数据
int send_bytes;
int send_total = 0;
char sendBuf[DEFAULT_BUFLEN] = "welcom!";
while (send_total < strlen(sendBuf) + 1)
{
send_bytes = send(ConnectSocket, sendBuf + send_total, strlen(sendBuf) + 1 - send_total, 0);
if (send_bytes == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
return 1;
}
else
{
send_total += send_bytes;
}
}
//从客户端接收数据
int recv_bytes;
char recvBuf[DEFAULT_BUFLEN] = "";
int recvbuflen = DEFAULT_BUFLEN;
recv_bytes = recv(ConnectSocket, recvBuf, recvbuflen, 0);
if (recv_bytes > 0)
printf("recv %d bytes data from cilent:%s\n", recv_bytes, recvBuf);
else if (recv_bytes == 0)
printf("Connection closed\n");
else
{
wprintf(L"recv failed with error: %d\n", WSAGetLastError());
closesocket(ConnectSocket);
return 1;
}
//关闭建立连接的套接字
closesocket(ConnectSocket);
return 0;
}
int main()
{
printf("Server\n");
int iResult;
WSADATA wsaData;
//加载套接字库
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed with error: %ld\n", iResult);
return 1;
}
//创建监听套接字
SOCKET ListenSocket;
ListenSocket = socket(AF_INET, SOCK_STREAM, 0);
if (ListenSocket == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
sockaddr_in addrServer;
addrServer.sin_family = AF_INET;
//inet_pton(AF_INET, "127.0.0.1", (VOID*)&addrServer.sin_addr.S_un.S_addr);
addrServer.sin_addr.S_un.S_addr = INADDR_ANY;
addrServer.sin_port = htons(6000);
//绑定本机IP地址和端口号
iResult = bind(ListenSocket, (sockaddr*)&addrServer, sizeof(sockaddr));
if (iResult == SOCKET_ERROR)
{
printf("bind failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
//设置套接字为监听模式
iResult = listen(ListenSocket, 10);
if (iResult == SOCKET_ERROR)
{
printf("listen failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
sockaddr_in addrClient;
int len = sizeof(sockaddr_in);
while (1)
{
//主线程接收客户连接请求
SOCKET ConnectSocket = accept(ListenSocket, (sockaddr*)&addrClient, &len);
if (ConnectSocket == INVALID_SOCKET)
{
printf("accept failed with error: %ld\n", WSAGetLastError());
closesocket(ListenSocket);
WSACleanup();
return 1;
}
char buf[100] = { 0 };
fprintf(stdout, "accept a connection,from %s:%d\n", inet_ntop(AF_INET, (VOID*)&addrClient.sin_addr, buf, 100), ntohs(addrClient.sin_port));
//创建的线程用来通信
HANDLE hThread = (HANDLE)_beginthreadex(NULL, 0, Thread1Fun, (void*)ConnectSocket, 0, NULL);
CloseHandle(hThread);
}
//关闭监听套接字
closesocket(ListenSocket);
//结束对套接字库的使用
WSACleanup();
return 0;
}
客户端流程:加载套接字库WSAStartup()—>创建套接字socket()—>连接服务器connect()—>和服务器进行通信recv()/send()—>关闭套接字closesocket()—>结束套接字库的使用WSACleanup()。
代码示例:
#include <stdio.h>
#include <Winsock2.h>
#include <Ws2tcpip.h>
#pragma comment(lib,"Ws2_32.lib")
#define DEFAULT_BUFLEN 512
int main()
{
printf("Client\n");
WSADATA wsaData;
int iResult;
//加载套接字库
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if (iResult != 0)
{
printf("WSAStartup failed with error: %ld\n", iResult);
return 1;
}
//创建套接字
SOCKET ClientSocket = socket(AF_INET, SOCK_STREAM, 0);
if (ClientSocket == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
sockaddr_in clientService;
clientService.sin_family = AF_INET;
//clientService.sin_addr.s_addr = inet_addr("127.0.0.1");
inet_pton(AF_INET, "127.0.0.1", (VOID*)&clientService.sin_addr.s_addr);
clientService.sin_port = htons(6000);
//连接服务器
iResult = connect(ClientSocket, (sockaddr*)&clientService, sizeof(sockaddr));
if (iResult == SOCKET_ERROR)
{
printf("connect function failed with error: %ld\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//从服务器接收数据
int recv_bytes;
char recvBuf[DEFAULT_BUFLEN] = "";
int recvbuflen = DEFAULT_BUFLEN;
recv_bytes = recv(ClientSocket, recvBuf, recvbuflen, 0);
if (recv_bytes > 0)
printf("recv %d bytes data from server:%s\n", recv_bytes, recvBuf);
else if (recv_bytes == 0)
printf("Connection closed\n");
else
{
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//向服务器发送数据
int send_bytes;
int send_total = 0;
char sendBuf[DEFAULT_BUFLEN] = "";
sprintf_s(sendBuf, DEFAULT_BUFLEN, "This is client!");
while (send_total < strlen(sendBuf) + 1)
{
send_bytes = send(ClientSocket, sendBuf + send_total, strlen(sendBuf) + 1 - send_total, 0);
if (send_bytes == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
else
{
send_total += send_bytes;
}
}
//关闭套接字
closesocket(ClientSocket);
//结束对套接字库的使用
WSACleanup();
return 0;
}
2、基于UDP的socket编程的接收端-发送端流程
接收端流程:加载套接字库WSAStartup()—>创建套接字socket()—>绑定套接字到本地地址和端口bind()—>等待接收数据recvfrom()—>关闭套接字closesocket()—>结束套接字库的使用WSACleanup()。
代码示例:
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
#define DEFAULT_BUFLEN 512
int main()
{
printf("Server\n");
int iResult;
WSADATA wsaData;
//加载套接字库
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult != 0)
{
printf("WSAStartup failed with error: %ld\n", iResult);
return 1;
}
//创建套接字
SOCKET SocketServer;
SocketServer = socket(AF_INET, SOCK_DGRAM, 0);
if(SocketServer == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
sockaddr_in addrServer;
addrServer.sin_family = AF_INET;
addrServer.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
addrServer.sin_port = htons(6000);
//绑定本机回送地址和端口号
iResult = bind(SocketServer, (sockaddr*)&addrServer, sizeof(sockaddr));
if(iResult == SOCKET_ERROR)
{
printf("bind failed with error: %ld\n", WSAGetLastError());
closesocket(SocketServer);
WSACleanup();
return 1;
}
//从客户端接收数据
int recv_bytes;
char recvBuf[DEFAULT_BUFLEN] = "";
int recvbuflen = DEFAULT_BUFLEN;
sockaddr_in addrClient;
int len = sizeof(sockaddr);
recv_bytes = recvfrom(SocketServer, recvBuf, recvbuflen, 0, (sockaddr*)&addrClient, &len);
if(recv_bytes > 0)
printf("recv %d bytes data from %s.%d cilent:%s\n",recv_bytes,inet_ntoa(addrClient.sin_addr),ntohs(addrClient.sin_port),recvBuf);
else if (recv_bytes == 0)
printf("Connection closed\n");
else
{
wprintf(L"recv failed with error: %d\n", WSAGetLastError());
closesocket(SocketServer);
return 1;
}
if(recv_bytes > 0)
{
//向客户端发送数据
int send_bytes;
int send_total = 0;
char sendBuf[DEFAULT_BUFLEN] = "recv data completed!";
while(send_total < strlen(sendBuf)+1)
{
send_bytes = sendto(SocketServer,sendBuf + send_total,strlen(sendBuf)+1-send_total,0,(sockaddr*)&addrClient,len);
if(send_bytes == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(SocketServer);
return 1;
}
else
{
send_total += send_bytes;
}
}
}
//关闭套接字
closesocket(SocketServer);
//结束对套接字库的使用
WSACleanup();
return 0;
}
发送端流程:加载套接字库WSAStartup()—>创建套接字socket()—>向服务器发送数据sendto()—>关闭套接字closesocket()—>结束使用套接字库WSACleanup()。
代码示例:
#include <stdio.h>
#include <Winsock2.h>
#pragma comment(lib,"Ws2_32.lib")
#define DEFAULT_BUFLEN 512
int main()
{
printf("Client\n");
WSADATA wsaData;
int iResult;
//加载套接字库
iResult = WSAStartup(MAKEWORD(2, 2), &wsaData);
if(iResult != 0)
{
printf("WSAStartup failed with error: %ld\n", iResult);
return 1;
}
//创建套接字
SOCKET ClientSocket = socket(AF_INET, SOCK_DGRAM, 0);
if(ClientSocket == INVALID_SOCKET)
{
printf("socket failed with error: %ld\n", WSAGetLastError());
WSACleanup();
return 1;
}
sockaddr_in addrServer;
addrServer.sin_family = AF_INET;
addrServer.sin_addr.s_addr = inet_addr("127.0.0.1");
addrServer.sin_port = htons(6000);
int len = sizeof(sockaddr);
//向服务器发送数据
int send_bytes;
int send_total = 0;
char sendBuf[DEFAULT_BUFLEN] = "";
sprintf(sendBuf, "This is client!");
while(send_total < strlen(sendBuf)+1)
{
send_bytes = sendto(ClientSocket,sendBuf + send_total,strlen(sendBuf)+1-send_total,0,(sockaddr*)&addrServer,len);
if(send_bytes == SOCKET_ERROR)
{
printf("send failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
else
{
send_total += send_bytes;
}
}
//从服务器接收数据
int recv_bytes;
char recvBuf[DEFAULT_BUFLEN] = "";
int recvbuflen = DEFAULT_BUFLEN;
recv_bytes = recvfrom(ClientSocket,recvBuf,recvbuflen,0,(sockaddr*)&addrServer,&len);
if(recv_bytes > 0)
printf("recv %d bytes data from server:%s\n", recv_bytes, recvBuf);
else if (recv_bytes == 0)
printf("Connection closed\n");
else
{
printf("recv failed with error: %d\n", WSAGetLastError());
closesocket(ClientSocket);
WSACleanup();
return 1;
}
//关闭套接字
closesocket(ClientSocket);
//结束对套接字库的使用
WSACleanup();
return 0;
}