实践:使用socket实现跨进程通信(C语言)
实践:使用socket实现跨进程通信(C语言)
材料归档
- 链接:https://pan.baidu.com/s/1cQREPzKZFGvHlNOEMlroEA
- 提取码:vhq8
- 归档路径:材料归档\20210919_实践:使用socket实现跨进程通信(C语言)
功能描述
使用socket通信,实现服务端功能和客户端功能,并进行消息的交互,实现跨进程通信。
功能演示
第一步:打开Linux操作窗口,启动Server进程。
./test_socket server 127.0.0.1 1500
第二步:打开另一个Linux操作窗口,启动Client进程。可以观察到Client收到Server的消息,同时观察Server日志可以发现发送成功。
./test_socket client 127.0.0.1 1500
第三步:查看抓包。可以看到对应的TCP消息报文。
相关代码
test_socket.h
#ifndef __TEST_SOCKET_H__
#define __TEST_SOCKET_H__
#define VOS_OK 0
#define VOS_ERR 1
#define VOS_TRUE 1
#define VOS_FALSE 0
typedef void VOID;
typedef char CHAR;
typedef int INT32;
typedef unsigned char UINT8;
typedef unsigned short UINT16;
typedef unsigned int UINT32;
typedef unsigned long long UINT64;
#define SOCK_ERR(fmt...) do { \
printf("[SOCK]" fmt); \
printf("\r\n"); \
} while(0)
#define SOCK_PROCESS_TYPE_NAME_SERVER "server"
#define SOCK_PROCESS_TYPE_NAME_CLIENT "client"
#define SOCK_PROCESS_TYPE_SERVER 0
#define SOCK_PROCESS_TYPE_CLIENT 1
#define SOCK_DEFAULT_DST_ADDR "127.0.0.1"
#define SOCK_DEFAULT_DST_PORT 1500
typedef struct {
UINT16 family;
UINT16 port;
UINT32 addr;
UINT8 resv[8];
} SOCK_ADDR_S;
typedef struct {
UINT32 type;
CHAR* addr;
UINT16 port;
} SOCK_PARA_S;
#endif
test_socket.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include "test_socket.h"
VOID SOCK_InitPara(SOCK_PARA_S *pPara, int argc, char *argv[])
{
argc--;
argv++;
if (argc > 0 && strcmp(SOCK_PROCESS_TYPE_NAME_CLIENT, argv[0]) == 0) {
pPara->type = SOCK_PROCESS_TYPE_CLIENT;
} else {
pPara->type = SOCK_PROCESS_TYPE_SERVER;
}
if (argc > 1) {
pPara->addr = argv[1];
} else {
pPara->addr = SOCK_DEFAULT_DST_ADDR;
}
if (argc > 2) {
pPara->port = (UINT16)atol(argv[2]);
} else {
pPara->port = SOCK_DEFAULT_DST_PORT;
}
}
UINT32 SOCK_MainServer(SOCK_PARA_S *pPara)
{
INT32 ret;
// socket
INT32 sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
SOCK_ERR("socket Fail!");
return VOS_ERR;
}
SOCK_ERR("socket(%d) create ok", sock);
// bind
SOCK_ADDR_S addr;
addr.family = AF_INET;
addr.port = htons(pPara->port);
addr.addr = inet_addr(pPara->addr);
ret = bind(sock, (struct sockaddr *)&addr, sizeof(SOCK_ADDR_S));
if (ret < 0) {
SOCK_ERR("socket bind Err(%d)!", ret);
return VOS_ERR;
}
// listen
ret = listen(sock, 5);
if (ret != VOS_OK) {
SOCK_ERR("socket listen Err(%d)!", ret);
return VOS_ERR;
}
SOCK_ERR("socket accept ...");
// accept
INT32 clientSock;
SOCK_ADDR_S clientAddr;
UINT32 clientAddrLen = sizeof(SOCK_ADDR_S); // 注意:这里得是有效值
while (VOS_TRUE) {
clientSock = accept(sock, (struct sockaddr *)&clientAddr, &clientAddrLen);
if (clientSock == -1) {
SOCK_ERR("socket accept Fail(%d)", clientSock);
} else {
SOCK_ERR("socket accept Succ");
ret = send(clientSock, "Hello World!", 12, 0);
if (ret == -1) {
SOCK_ERR("socket send Fail");
} else {
SOCK_ERR("socket send Succ");
}
}
}
return VOS_OK;
}
UINT32 SOCK_MainClient(SOCK_PARA_S *pPara)
{
INT32 ret;
// socket
INT32 sock = socket(AF_INET, SOCK_STREAM, 0);
if (sock == -1) {
SOCK_ERR("socket Fail!");
return VOS_ERR;
}
SOCK_ERR("socket(%d) create ok", sock);
// connet
SOCK_ADDR_S addr;
addr.family = AF_INET;
addr.port = htons(pPara->port);
addr.addr = inet_addr(pPara->addr);
ret = connect(sock, (struct sockaddr *)&addr, sizeof(SOCK_ADDR_S));
if (ret == -1) {
SOCK_ERR("socket connet Fail(%d)!", ret);
return VOS_ERR;
}
// recv
char buf[100] = {0};
ret = recv(sock, buf, 100, 0);
if (ret == -1) {
SOCK_ERR("socket recv Fail(%d)!", ret);
return VOS_ERR;
}
SOCK_ERR("socket recv Succ(%s)!", buf);
return VOS_ERR;
}
int main(int argc, char *argv[])
{
SOCK_PARA_S para;
SOCK_InitPara(¶, argc, argv);
SOCK_ERR("test socket start");
if (para.type == SOCK_PROCESS_TYPE_SERVER) {
(VOID)SOCK_MainServer(¶);
} else {
(VOID)SOCK_MainClient(¶);
}
SOCK_ERR("test socket end");
return VOS_OK;
}
剑指 Offer