Socket编程相关例子
转载自:https://blog.csdn.net/xiaoquantouer/article/details/58001960
TCP:
服务器端:
#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h> //inet_ntop函数使用所要加的头文件
using namespace std;
#pragma comment(lib, "Ws2_32.lib")
#pragma warning(disable:4996);
int main()
{
//初始化socket库
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) //请求2.2版本的WinSock库,成功则返回0
{
return 0; //失败则退出
}
//检测请求版本号是否正确,通常可以不加
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
WSACleanup(); //不正确则清除信息
return 0;
}
//创建监听套接字
SOCKET slisten = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (slisten == INVALID_SOCKET)
{
cout << "socket error!" << endl;
return 0;
}
sockaddr_in sin;
sin.sin_family = AF_INET;
sin.sin_port = htons(8888);
sin.sin_addr.S_un.S_addr = INADDR_ANY;
//sin.sin_addr.S_un.S_addr = inet_addr("172.16.2.6");
if (bind(slisten, (const sockaddr*)&sin, sizeof(sin)) == SOCKET_ERROR)
{
cout << "bind error!" << endl;
}
if (listen(slisten, SOMAXCONN) ==SOCKET_ERROR)
{
cout << "listen error!" << endl;
}
SOCKET sClient;
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
char revData[255];
cout << "等待链接..." << endl;
while (true)
{
sClient = accept(slisten, (sockaddr*)&remoteAddr, &nAddrlen);
if (sClient == INVALID_SOCKET)
{
cout << "accept error!" << endl;
continue;
}
char str[INET_ADDRSTRLEN];
inet_ntop(AF_INET, &remoteAddr.sin_addr, str, sizeof(str));
cout << "接收到一个连接地址:" << str << endl;
//int n = 4;
while (true)
{
int ret = recv(sClient, revData, 255, 0);
if (ret > 0)
{
revData[ret] = 0x00;
cout << revData << endl;
}
else if (ret == SOCKET_ERROR)
{
cout << "当前连接关闭!" << endl;
break;
}
//发送数据
const char* sendData = "服务器:你好,TCP客户端!\n";
send(sClient, sendData, strlen(sendData), 0);
}
closesocket(sClient);
}
closesocket(slisten);
WSACleanup();
return 0;
}
客户端:
#include "stdafx.h"
#include <WinSock2.h>
#include <windows.h>
#include <iostream>
#include <WS2tcpip.h>
#include <string>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996);
int main()
{
WSADATA data;
if (WSAStartup(MAKEWORD(2, 2), &data) != 0)
{
cout << "WSAStartup error!" << endl;
return 0;
}
SOCKET sclient = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if (sclient == INVALID_SOCKET)
{
cout << "invalid socket!" << endl;
return 0;
}
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(8888);
serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
if (connect(sclient, (const sockaddr*)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
{
//连接失败
cout << "connect error!" << endl;
closesocket(sclient);
return 0;
}
else
{
cout << "connect success!" << endl;
}
while (true)
{
//连接成功后发送信息
string data;
cin >> data;
const char* sendData;
sendData = data.c_str();
if (send(sclient, sendData, strlen(sendData), 0)==SOCKET_ERROR)
{
cout << "send error!" << endl;
cout << WSAGetLastError() << endl;
}
//接收信息
char recvData[255];
int ret = recv(sclient, recvData, 255, 0);
if (ret > 0)
{
recvData[ret] = 0x00;
cout << recvData << endl;
}
}
closesocket(sclient);
WSACleanup();
return 0;
}
UDP:
服务器端:
#include "stdafx.h"
#include <iostream>
#include <WinSock2.h>
#include <WS2tcpip.h> //inet_ntop函数使用所要加的头文件
using namespace std;
#pragma comment(lib, "Ws2_32.lib")
#pragma warning(disable:4996);
int main()
{
//初始化socket库
WSADATA wsaData;
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0) //请求2.2版本的WinSock库,成功则返回0
{
return 0; //失败则退出
}
//检测请求版本号是否正确,通常可以不加
if (LOBYTE(wsaData.wVersion) != 2 || HIBYTE(wsaData.wVersion) != 2)
{
WSACleanup(); //不正确则清除信息
return 0;
}
//创建监听套接字
SOCKET serSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (serSocket == INVALID_SOCKET)
{
cout << "socket error!" << endl;
return 0;
}
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(8888);
serAddr.sin_addr.S_un.S_addr = INADDR_ANY;
//sin.sin_addr.S_un.S_addr = inet_addr("172.16.2.6");
if (bind(serSocket, (const sockaddr*)&serAddr, sizeof(serAddr)) == SOCKET_ERROR)
{
cout << "bind error!" << endl;
closesocket(serSocket);
return 0;
}
sockaddr_in remoteAddr;
int nAddrlen = sizeof(remoteAddr);
while (true)
{
char recvData[255];
cout << "等待连接....." << endl;
int ret = recvfrom(serSocket, recvData, strlen(recvData), 0, (sockaddr*)&remoteAddr, &nAddrlen);
if (ret > 0)
{
recvData[ret] = 0x00;
printf("接受到一个连接:%s\r\n", inet_ntoa(remoteAddr.sin_addr));
printf(recvData);
}
const char* sendData = "一个来自服务端的UDP数据包\n";
sendto(serSocket, sendData, strlen(sendData), 0, (sockaddr*)&remoteAddr, nAddrlen);
}
closesocket(serSocket);
WSACleanup();
return 0;
}
客户端:
#include "stdafx.h"
#include <WinSock2.h>
#include <windows.h>
#include <iostream>
#include <WS2tcpip.h>
#include <string>
using namespace std;
#pragma comment(lib,"ws2_32.lib")
#pragma warning(disable:4996);
int main()
{
WSADATA data;
if (WSAStartup(MAKEWORD(2, 2), &data) != 0)
{
cout << "WSAStartup error!" << endl;
return 0;
}
SOCKET sclient = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sclient == INVALID_SOCKET)
{
cout << "invalid socket!" << endl;
return 0;
}
sockaddr_in serAddr;
serAddr.sin_family = AF_INET;
serAddr.sin_port = htons(8888);
serAddr.sin_addr.S_un.S_addr = inet_addr("127.0.0.1");
int len = sizeof(serAddr);
const char* sendData = "来自客户端的数据包.\n";
sendto(sclient, sendData, strlen(sendData), 0, (sockaddr*)&serAddr, len);
char recvData[255];
int ret = recvfrom(sclient, recvData, 255, 0, (sockaddr*)&serAddr, &len);
if (ret > 0)
{
recvData[ret] = 0x00;
printf(recvData);
}
closesocket(sclient);
WSACleanup();
return 0;
}
Windows下的socket程序和Linux区别:
(1) Windows下的socket程序依赖Winsock.dll或ws2_32.dll,必须提前加载。DLL有两种加载方式。
(2) Linux使用“文件描述符”的概念,而Windows使用“文件句柄”的概念;Linux不区分socket文件和普通文件,而Windows区分;Linux下socket()函数的返回值为int类型,而Windows下为SOCKET类型,也就是句柄。
(3) Linux下使用read()/write()函数读写,而Windows下使用recv()/send()函数发送和接收
(4) 关闭socket时,Linux使用close()函数,而Windows使用closesocket()函数。