这篇文章是笔者在复习的时候整理出来的,希望对大家有所帮助。
两台计算机在进行网络通信的时候,除了需要有可靠的物理连接之外,还需要对应的软件才能进行通信,这个软件需要程序员手动编写。两台进行通信的计算机平台和系统都有可能不同,使用使用系统提供的一组API可以让我们忽略这种差异性。这类API我们称之为套接字。
套接字(Socket)并不是指一个独立的软件,而是网络通信的编程接口(API),是程序员用来实现网络通信的工具。以下是更准确的解释:
bind()
、connect()
、send()
等)实现网络通信。sys/socket.h
、Windows的Winsock.h
),编程语言(如Python的socket
模块)会进一步封装这些接口。read()
/write()
),只是数据通过网络传输而非本地磁盘。套接字是程序员用来实现网络通信的编程接口(API),它基于操作系统提供的网络协议栈,通过代码控制通信行为,而非一个独立的软件。 物理连接由硬件和底层协议保证,套接字则负责在软件层面建立、管理和终止通信。
套接字是网络编程的核心概念,贯穿网络编程学习的整个过程。
首先需要明白。信息的发送和接收是不同的,需要使用不同的代码实现。
使用套接字进行接收信息的网络编程:
socket
函数bind
函数,给套接字分配地址信息(IP和端口)listen
函数把套接字转换为可接收连接的状态accept
函数受理连接使用套接字进行发送信息的网络编程:
connect
函数先直接给出在Windows上使用c/c++进行网络编程的基本代码结构,先给出TCP的,UDP的以后会出专门的复习笔记。
关于TCP的更详细地介绍,以后会有专门的复习笔记,这里只是简单地给出代码。先给出服务端的:
#include
#include
#include
//错误处理
void ErrorHandling(char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
int main(int argc, char* argv[])
{
WSADATA wsaData;//套接字信息
SOCKET hServSock, hClntSock;//服务端和客户端套接字
SOCKADDR_IN servAddr, clntAddr;//地址信息
int szClntAddr;
char message[] = "Hello World!";
if (argc != 2)
{
printf("Usage : %s \n" , argv[0]);
exit(1);
}
//Windows上必须初始化套接字
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
ErrorHandling(const_cast<char*>("WSAStartup() error"));
}
//创建套接字
hServSock = socket(PF_INET, SOCK_STREAM, 0);
if (hServSock == INVALID_SOCKET)
{
ErrorHandling(const_cast<char*>("socket() error"));
}
//填充地址信息
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
servAddr.sin_addr.s_addr = htonl(INADDR_ANY);
servAddr.sin_port = htons(atoi(argv[1]));
//将地址信息与套接字关联起来
if (bind(hServSock, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
{
ErrorHandling(const_cast<char*>("bind() error"));
}
//将套接字转换为接听状态
if (listen(hServSock, 5) == SOCKET_ERROR)
{
ErrorHandling(const_cast<char*>("listen() error"));
}
//处理连接请求
szClntAddr = sizeof(clntAddr);
hClntSock = accept(hServSock, (SOCKADDR*)&clntAddr, &szClntAddr);
if (hClntSock == INVALID_SOCKET)
{
ErrorHandling(const_cast<char*>("accept() error"));
}
//发送数据
send(hClntSock, message, sizeof(message), 0);
//关闭套接字
closesocket(hClntSock);
closesocket(hServSock);
WSACleanup();
return 0;
}
下面的代码是客户端的:
#include
#include
#include
#include
void ErrorHandling(char* message)
{
fputs(message, stderr);
fputc('\n', stderr);
exit(1);
}
int main(int argc, char* argv[])
{
WSADATA wsaData;
SOCKET hSocket;
SOCKADDR_IN servAddr;
char message[30];
int strLen;
if (argc != 3)
{
printf("Usage : %s \n" , argv[0]);
exit(1);
}
if (WSAStartup(MAKEWORD(2, 2), &wsaData) != 0)
{
ErrorHandling(const_cast<char*>("WSAStartup() error"));
}
hSocket = socket(PF_INET, SOCK_STREAM, 0);
if (hSocket == INVALID_SOCKET)
{
ErrorHandling(const_cast<char*>("socket() error"));
}
memset(&servAddr, 0, sizeof(servAddr));
servAddr.sin_family = AF_INET;
inet_pton(AF_INET,argv[1],&servAddr.sin_addr.s_addr);
servAddr.sin_port = htons(atoi(argv[2]));
//连接服务器
if (connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR)
{
ErrorHandling(const_cast<char*>("connect() error"));
}
//接收信息
strLen = recv(hSocket, message, sizeof(message) - 1, 0);
if (strLen == -1)
{
ErrorHandling(const_cast<char*>("recv() error"));
}
printf("message from server: %s\n", message);
closesocket(hSocket);
WSACleanup();
return 0;
}