- 前言
- 一、基础知识
- 1.Internet套接字
- 2.socket相关结构体
- 3. server&client交互过程
- 二、简单实例
前言 本文内容分两个部分: socket编程基础知识 与 简单实例。
提示:阅读前有一定计算机网络知识的基础
一、基础知识 1.Internet套接字【介绍】
应用层 与 传输层 的通道,由ip地址 + 端口号
【分类】
流格式(stream sockets)
sock_stream: 全双工可靠面向连接的传输,tcp
数据包格式(datagram socket)
sock_dgram: 无连接传输,速度更快,udp
- socket描述符:int类型
注意:网络字节顺序(Network Byte Order)与 本机字节顺序(Host Byte Order) - struct sockaddr:
struct sockaddr {
unsigned short sa_family; //协议族
char sa_data[14]; //协议地址
};
- struct sockaddr_in:与sockaddr等价,常用
struct sockaddr_in {
short int sin_family; //通信类型
unsigned short int sin_port; //端口
struct in_addr sin_addr; //ip
unsigned char sin_zero[8]; //同sockaddr长度相同
};
- struct in_addr:
struct in_addr {
unsigned long s_addr;
};
- 本机转换
n:网络顺序,h:本机顺序,s:short,l:long
htons()–“Host to Network Short”
htonl()–“Host to Network Long”
ntohs()–“Network to Host Short”
ntohl()–“Network to Host Long”
注:
本机字节顺序:与cpu架构有关,x86为小端序
网络字节顺序:大端序 - ip地址类型转换
p or a:表达形式(ascii字符串)
n:数值形式(二进制数–存在struct in_addr中)
ina.sin_addr.s_addr = inet_addr("132.241.5.10");
printf("%s",inet_ntoa(ina.sin_addr));
int inet_pton(int family, const char *strptr, void *addrptr);
//将表达形式(字符串)转化为数值格式(结构体)
//返回值:若成功则为1,若输入不是有效的表达式则为0,若出错则为-1
const char * inet_ntop(int family, const void *addrptr, char *strptr, size_t len);
//将数值格式(结构体)转化为表达形式(字符串)
//返回值:若成功则为指向结构的指针,若出错则为NULL
3. server&client交互过程
1.socket 函数 : 创建套接字
int socket(int domain, int type, int protocol)
domain : PF_INET, PF_INET6
type : SOCK_STREAM, SOCK_DGRAM
protocol : IPPROTO_TCP, IPPROTO_UDP
2.bind 函数 : 绑定(ip地址,端口号), 服务端使用
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen)
sockfd : 服务器socket
addr : 服务器地址
3.listen 函数 : 服务端监听socket,等待连接
int listen(int sockfd, int backlog)
sockfd : 服务器socket
backlog : 排队队列
4.connect 函数 : 客户端发送的连接请求
int connect(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
sockfd : 客户端socket
addr : 服务器地址
5.accept函数 : 服务器监听发现请求,接收
int accept(int sockfd, struct sockaddr *addr, socklen_t addrlen)
sockfd : 服务器socket
addr : 客户端地址
注:服务端socket: 监听socket、连接socket
监听socket:服务器生命周期仅创建一个
连接socket:每次accept返回新套接字
【server】
注:链接时添加-lws2_32
#include#include #include using namespace std; #pragma comment(lib, "ws2_32.lib") int main(int argc, char* argv[]) { //初始化DLL, 调用winsock2.2 WORD sockVersion = MAKEWORD(2, 2); WSADATA wsdata; if (WSAStartup(sockVersion, &wsdata) != 0) { return 1; } //创建套接字描述符 SOCKET listen_sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (listen_sock == -1) { cout << "error: create server listen_socket" << endl; return 1; } sockaddr_in sockAddr; sockAddr.sin_family = AF_INET; sockAddr.sin_port = htons(8888); sockAddr.sin_addr.s_addr = INADDR_ANY; //绑定sockaddr_in 到套接字描述符 if (bind(listen_sock, (sockaddr*)&sockAddr, sizeof(sockAddr)) == SOCKET_ERROR){ cout << "error: bind" << endl; return 1; } //listen if(listen(listen_sock, 5) == -1) { cout << "Error: listen" << endl; return 1; } SOCKET connect_sock; sockaddr_in client_sin; char msg[100]; //存储传送的消息 int flag = 0; //是否已经连接上 int len = sizeof(client_sin); while (true){ //创建连接socket if(!flag) cout << "listening..." << endl; connect_sock = accept(listen_sock, (sockaddr*)&client_sin, &len); if (connect_sock == -1) { cout << "error:accept" << endl; flag = 0; return 1; } if(!flag) cout << "connected:" << inet_ntoa(client_sin.sin_addr) << endl; //连接成功 flag = 1; //服务器recv int num = recv(connect_sock, msg, 100, 0); if (num > 0) { msg[num] = ' '; cout <<"Client say: "<< msg << endl; } //服务器send string data; getline(cin, data); const char * sendData; sendData = data.c_str(); send(connect_sock, sendData, strlen(sendData), 0); //关闭连接 closesocket(connect_sock); } closesocket(listen_sock); WSACleanup(); return 0; }
【client】
#include#include #include using namespace std; #pragma comment(lib, "ws2_32.lib") int main() { WORD sockVersion = MAKEWORD(2, 2); WSADATA data; if (WSAStartup(sockVersion, &data) != 0) { return 1; } while (true){ //创建套接字描述符 SOCKET clientSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); if (clientSocket == INVALID_SOCKET){ cout << "Socket error" << endl; return 1; } sockaddr_in sock_in; sock_in.sin_family = AF_INET; sock_in.sin_port = htons(8888); sock_in.sin_addr.s_addr = inet_addr("127.0.0.1"); //connect if (connect(clientSocket, (sockaddr*)&sock_in, sizeof(sock_in) )== SOCKET_ERROR){ cout << "Connect error" << endl; return 1; } //send string data; getline(cin, data); const char * msg; msg = data.c_str(); send(clientSocket, msg, strlen(msg), 0); //recv char revdata[100]; int num = recv(clientSocket, revdata, 100, 0); if (num > 0){ revdata[num] = ' '; cout <<"Sever say:"<< revdata << endl; } closesocket(clientSocket); } WSACleanup(); return 0; }



