TcpServer
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#include
#include
#include
#include
#pragma comment(lib,"ws2_32.lib")
std::mutex g_Mutex;
bool g_IsQuit = false;
void QuitServer()
{
while (!g_IsQuit)
{
short key = GetAsyncKeyState('A');
if(key&0x0001)
{
g_Mutex.lock();
g_IsQuit = true;
g_Mutex.unlock();
}
std::this_thread::sleep_for(std::chrono::milliseconds(1));
}
}
int main()
{
//1.初始化网络环境
WORD wVersion = MAKEWORD(2, 2);
WSADATA wsaData;
int err = WSAStartup(wVersion, &wsaData);
if (err != 0)
{
printf("网络初始化错误,错误代码%d\n", err);
system("pause");
return 0;
}
//2.创建监听套接字
SOCKET listenSock = socket(
AF_INET,
SOCK_STREAM,
IPPROTO_TCP
);
if (INVALID_SOCKET == listenSock)
{
printf("监听套接字创建失败\n");
WSACleanup();
system("pause");
return 0;
}
//3.设置服务器的端口信息
sockaddr_in sin;
sin.sin_port = htons(6666);
sin.sin_family = AF_INET;
sin.sin_addr.S_un.S_addr = htonl(INADDR_ANY);//任意ip
//4.绑定地址信息到监听套接字
if (SOCKET_ERROR == bind(listenSock, (sockaddr*)&sin, sizeof(sin)))
{
printf("绑定监听套接字创建失败\n");
closesocket(listenSock);
WSACleanup();
system("pause");
return 0;
}
//5.开始监听
if (SOCKET_ERROR == listen(listenSock, 100))
{
printf("监听出现错误\n");
closesocket(listenSock);
WSACleanup();
system("pause");
return 0;
}
//6.收发信息
sockaddr_in clientaddinfo;
int addlen = sizeof(clientaddinfo);
SOCKET clientsock;
clientsock = accept(listenSock, (sockaddr*)&clientaddinfo, &addlen);
if (INVALID_SOCKET == clientsock)
{
printf("Accept错误\n");
closesocket(listenSock);
WSACleanup();
system("pause");
return 0;
}
//使用多线程转发和接收信息
while (!g_IsQuit)
{
printf("接收到一个客户:%d,IP:%s,Port:&d\n",
clientsock,
inet_ntoa(clientaddinfo.sin_addr),
clientaddinfo.sin_port);
char buf[MAX_PATH] = {};
recv(clientsock, buf, MAX_PATH - 1, 0);
printf("接收到的数据:%s\n", buf);
send(clientsock, "this is my backdata!", strlen("this is my backdata!") + 1,0);
}
//7.关闭套接字和网络环境
closesocket(clientsock);
closesocket(listenSock);
WSACleanup();
system("pause");
return 0;
}
Linux跨平台网络客户端
#ifdef _WIN32
#define WIN32_LEAN_AND_MEAN
#define _WINSOCK_DEPRECATED_NO_WARNINGS
#include
#include
#pragma comment(lib,"ws2_32.lib")
#else
#include
#include
#include
#define MAX_PATH 260
typedef int SOCKET;
#define INVALID_SOCKET (SOCKET)(~0)
#define SOCKET_ERROR (-1)
#define WSACleanup() //
#endif
#include
#include
#include
#include
using namespace std;
bool g_IsQuit = false;
bool g_IsSend = false;
char g_SendBuffer[MAX_PATH];
mutex g_Mutex1;
mutex g_Mutex2;
void InputData()
{
while (!g_IsQuit )
{
printf("input msg:\n");
scanf("%s",g_SendBuffer);
if (strcmp(g_SendBuffer,"exit")==0)
{
g_Mutex1.lock();
g_IsQuit = true;
g_Mutex1.unlock();
break;
}else if (!g_IsSend)
{
g_Mutex2.lock();
g_IsSend = true;
g_Mutex2.unlock();
}
this_thread::sleep_for(chrono::milliseconds(1));
}
}
int main()
{
#ifdef _WIN32
WORD wVersion = MAKEWORD(2, 2);
WSADATA wsaData;
int err = WSAStartup(wVersion, &wsaData);
if (err != 0)
{
printf("初始化错误%d\n", err);
system("pause");
return 0;
}
#endif
SOCKET clientSock = socket(
AF_INET,
SOCK_STREAM,
IPPROTO_TCP
);
if (INVALID_SOCKET == clientSock)
{
printf("create clientsocket failed\n");
WSACleanup();
system("pause");
return 0;
}
sockaddr_in sin;
sin.sin_port = htons(12345);
sin.sin_family = AF_INET;
#ifdef _WIN32
sin.sin_addr.S_un.S_addr = inet_addr("192.168.1.2");
#else
sin.sin_addr.s_addr = inet_addr("192.168.1.2");
#endif
if (SOCKET_ERROR == connect(clientSock, (sockaddr*)&sin, sizeof(sin)))
{
printf("错误\n");
#ifdef _WIN32
closesocket(clientSock);
#else
close(clientSock);
#endif
WSACleanup();
system("pause");
return 0;
}
thread inputthread(InputData);
inputthread.detach();
char recvdata[MAX_PATH] = {};
while (!g_IsQuit)
{
if (g_IsSend)
{
printf("start send data\n");
send(clientSock,g_SendBuffer, strlen(g_SendBuffer) + 1, 0);
printf("start recv data\n");
recv(clientSock, recvdata, MAX_PATH, 0);
printf("reved msg:%s\n", recvdata);
g_Mutex2.lock();
g_IsSend = false;
g_Mutex2.unlock();
printf("lock end\n");
}
this_thread::sleep_for(chrono::milliseconds(1));
}
#ifdef _WIN32
closesocket(clientSock);
#else
close(clientSock);
#endif
WSACleanup();
return 0;
}
总结
- 跨平台注意编码
- 通过使用内置的宏,可以进行操作系统判断 #ifdef _WIN32 #endif
- arpa/inet.h:IP地址转换