tcp客户端
// Service.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
#include <WinSock2.h>
typedef struct
{
SOCKET sockClient;
char szIp[16];
DWORD dwThreadName;
}RecvThread;
DWORD WINAPI ThreadRecv(LPVOID lpParam);
CRITICAL_SECTION g_c;//定义临界区
int main()
{
WSADATA wd;
if (0 != WSAStartup(MAKEWORD(2, 2), &wd))//WSAStartup初始化WinSock
{
WSACleanup();
}
InitializeCriticalSection(&g_c);//初始化临界区
SOCKET sockListen = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);//socket() 创建套接字,监听通道
SOCKADDR_IN addrListen;//sockaddr的缺陷是:sa_data把目标地址和端口信息混在一起了;SOCKADDR_IN结构体解决了sockaddr的缺陷,把port和addr 分开储存在两个变量中
addrListen.sin_family = AF_INET;
addrListen.sin_addr.s_addr = inet_addr("0.0.0.0");
addrListen.sin_port = htons(2021);
/*addrListen.sin_addr.s_addr = inet_addr("196.168.0.14");
addrListen.sin_port = htons(1025);*/
if (SOCKET_ERROR == bind(sockListen, (sockaddr *)&addrListen, sizeof(addrListen)))//bind绑定,将套接字和地址以及端口绑定;指向要分配给绑定套接字的本地地址的sockaddr结构的指针
{
int nErr = WSAGetLastError();
closesocket(sockListen);
WSACleanup();
return -1;
}
if (SOCKET_ERROR == listen(sockListen, 5))//listen() 监听,用于监听sockListen处,等待connect()发过来的连接请求
//通过 listen() 函数可以让套接字进入被动监听状态;所谓被动监听,是指当没有客户端请求时,套接字处于“睡眠”状态,只有当接收到客户端请求时,套接字才会被“唤醒”来响应请求
{
int nErr = WSAGetLastError();
closesocket(sockListen);
WSACleanup();
}
SOCKADDR_IN ClientAddr;
int nLen = sizeof(ClientAddr);
while (true)
{
RecvThread* pRecv = new RecvThread;
pRecv->sockClient = accept(sockListen, (sockaddr*)&ClientAddr, &nLen);//当套接字处于监听状态时,可以通过 accept() 函数来接收客户端请求
//返回一个新的套接字来和客户端通信,sockaddr 保存了客户端的IP地址和端口号,而 sock 是服务器端的套接字
//返回非负整数,该整数是接收到套接字的描述符
strcpy(pRecv->szIp, inet_ntoa(ClientAddr.sin_addr));
cout << pRecv->szIp << " login " << endl;
CloseHandle(CreateThread(NULL, 0, ThreadRecv, (LPVOID)pRecv, 0, &pRecv->dwThreadName));
}
DeleteCriticalSection(&g_c);//删除临界区
WSACleanup();//关闭WinSock
return 0;
}
DWORD WINAPI ThreadRecv(LPVOID lpParam)
{
char szBuf[255] = "";
int nRes = 0;
RecvThread* p = (RecvThread*)lpParam;
while (1)
{
nRes = recv(p->sockClient, szBuf, 255, 0);//通过已经建立连接的套接字来获取
if (SOCKET_ERROR == nRes)
{
int nErr = WSAGetLastError();
break;
}
EnterCriticalSection(&g_c);//进入临界区
cout << "client:" << szBuf << endl;
LeaveCriticalSection(&g_c);//退出临界区
if (0 == strcmp(szBuf, "exit"))
{
break;
}
}
cout << p->szIp << " out" << endl;
closesocket(p->sockClient);//关闭套接字
return 0;
}
tcp客户端
// Client.cpp : 此文件包含 "main" 函数。程序执行将在此处开始并结束。
//
#include <iostream>
using namespace std;
#include <WinSock2.h>
int main()
{
WSADATA wd;
if (0 != WSAStartup(MAKEWORD(2, 2), &wd))
{
WSACleanup();
}
SOCKET sockLink = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
SOCKADDR_IN addrListen;
addrListen.sin_family = AF_INET;
addrListen.sin_addr.s_addr = inet_addr("127.0.0.1");
addrListen.sin_port = htons(2021);
/*addrListen.sin_addr.s_addr = inet_addr("127.0.0.1");
addrListen.sin_port = htons(2021);*/
if (SOCKET_ERROR == connect(sockLink, (sockaddr*)&addrListen, sizeof(addrListen)))//connect() 发起连接请求,即套接字向该地址处,发送连接请求
{
int nErr = WSAGetLastError();
if (nErr == WSAEACCES)
{
cout << "error" << endl;
}
closesocket(sockLink);
WSACleanup();
return -1;
}
char szBuf[255] = "";
int nRes = 0;
while (1)
{
cout << "Input:";
cin >> szBuf;
nRes = send(sockLink, szBuf, strlen(szBuf) + 1, 0);//通过已经建立连接的套接字来发送
if (SOCKET_ERROR == nRes)
{
int nErr = WSAGetLastError();
break;
}
/*nRes = recv(sockLink, szBuf, 255, 0);
if (SOCKET_ERROR == nRes)
{
int nErr = WSAGetLastError();
break;
}
cout << "service:" << szBuf << endl;*/
}
closesocket(sockLink);
WSACleanup();
return 0;
}