Socket编程
1.客户端代码
//
// Created by zWX1143994 on 2023/4/14.
//
#include <iostream>
#include <arpa/inet.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <errno.h>
int main()
{
int client_socket = 0;
struct sockaddr_in clent_addr;
char buf[1024] = {};
int recvSize = 0;
client_socket = socket(AF_INET, SOCK_STREAM, 0);
if (client_socket < 0)
{
printf("socket Error: %s (errno: %d)\n", strerror(errno), errno);
_exit(0);
}
memset(&clent_addr, 0, sizeof(clent_addr));
clent_addr.sin_family = AF_INET;
clent_addr.sin_port = htons(1234);
clent_addr.sin_addr.s_addr = inet_addr("127.0.0.1");
//inet_pton(AF_INET, SERVER_IP, &clent_addr.sin_addr); //?
if (connect(client_socket, (struct sockaddr*)&clent_addr, sizeof(clent_addr)) < 0)
{
printf("connect Error: %s (errno: %d)\n", strerror(errno), errno);
_exit(0);
}
std::cout << "请输入信息:" << std::endl;
while (1)
{
fgets(buf, sizeof(buf), stdin);
//memset(&buf, 0, sizeof(buf));
write(client_socket, buf, sizeof(buf));
memset(&buf, 0, sizeof(buf));
recvSize = read(client_socket, buf, sizeof(buf));
if (recvSize == 0)
{
printf("Service is close!\n");
}
std::cout << "Service return Msg : " << buf << std::endl;
}
return 0;
}
2.服务端代码
//
// Created by zWX1143994 on 2023/3/30.
//
#include "stdio.h"
#include "string.h"
#include <sys/socket.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <errno.h>
#include <iostream>
#define SERVER_IP "127.0.0.1"
#define SERVER_PORT 1234
#define MAXSIZE 1024
int main(){
int server_socket = 0;
int clent_socket = 0;
char buf[MAXSIZE] = {};
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int recvSize = 0;
server_socket = socket(AF_INET,SOCK_STREAM,0);
if (server_socket < 0)
{
printf("socket() ERROR: %s (errno: %d)\n", strerror(errno), errno);
_exit(0);
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin_addr.s_addr = htonl(INADDR_ANY);
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_family = AF_INET;
if (bind(server_socket, (struct sockaddr*)&server_addr, sizeof(server_addr)) < 0)
{
printf("bind ERROR: %s (errno: %d)\n", strerror(errno), errno);
}
if (listen(server_socket,20) < 0)
{
printf("listen ERROR: %s (errno: %d)\n", strerror(errno), errno);
}
clent_socket = accept(server_socket, (struct sockaddr*)NULL, NULL);
if (clent_socket < 0)
{
printf("accept Error: %s (errno: %d)\n", strerror(errno), errno);
}
while (1)
{
memset(&buf, 0, MAXSIZE);
recvSize = read(clent_socket, buf, MAXSIZE);
if (recvSize == 0)
{
printf("client is disconnected!\n");
close(clent_socket);
break;
}
printf("recvMsg : %s", buf);
std::cin >> buf;
write(clent_socket, buf, MAXSIZE);
printf("Msg is send!\n");
}
close(clent_socket);
close(server_socket);
}
3.Socket编程的基本流程
Socket编程需遵循的一个基本原则就是在进程通信之前,必须建立完整的相关。
两个进程间的通信链路称为连接。连接两端的进程分别可以用一个三元组标识,即
(协议,本地地址,本地端口号),也被称为一个半相关(half-association),它描述了连接中的一端。
一个完整的连接可用一个五元组(协议,本地地址,本地端口号,远地地址,远地端口号)标识,该五元组也称为一个全相关。协议是连接中两个进程需要共同遵守的协议。
4.Socket编程的基本函数
4.1 socket接口函数
4.2 bind接口函数
4.3 connect接口函数
4.4 listen接口函数
4.5 accept接口函数
4.6 send函数和write函数
4.7 recv函数和read函数
5.Socket编程基本步骤
服务器端编程的步骤:
1:创建套接字(socket());
2:绑定套接字到一个IP地址和一个端口上(bind());
3:将套接字设置为监听模式等待连接请求(listen());
4:请求到来后,接受连接请求,返回一个新的对应于此次连接的套接字(accept());
5:用返回的套接字和客户端进行通信(send()/recv());
6:关闭套接字(closesocket)。
**客户端编程的步骤:
** 1:加载套接字库,创建套接字(socket());
2:向服务器发出连接请求(connect());
3:和服务器端进行通信(send()/recv());
4:关闭套接字,关闭加载的套接字库(closesocket())。
6. Socket基本类型简介
1.struct sockaddr结构:
struct sockaddr
{
unsigned short sa_family; /* 地址族, AF_xxx */
char sa_data[14]; /* 14 字节的协议地址 */
};
sa_family是地址家族,是“AF_xxx”的形式。常设为“AF_INET”,代表Internet(TCP/IP)地址族。sa_data则包含该socket的IP地址和端口号。 该结构的缺陷在于IP地址与端口号混合在一起。
2.sockaddr_in结构:
struct sockaddr_in
{
short int sin_family; /* 地址族 */
unsigned short int sin_port; /* 端口号 */
struct in_addr sin_addr; /* IP地址 */
unsigned char sin_zero[8]; /* 填充0 以保持与struct sockaddr同样大小 */
};
3.sockaddr 和 sockaddr_in的相互关系
一般先把sockaddr_in变量赋值后,强制类型转换后传入用sockaddr做参数的函数
sockaddr_in用于socket定义和赋值
sockaddr用于函数参数
in_addr sin_addr; /* IP地址 /
unsigned char sin_zero[8]; / 填充0 以保持与struct sockaddr同样大小 */
};
### 3.sockaddr 和 sockaddr_in的相互关系
一般先把sockaddr_in变量赋值后,强制类型转换后传入用sockaddr做参数的函数
**sockaddr_in**用于socket定义和赋值
**sockaddr**用于函数参数