1. 宏观
目的:实现简单的TCP通信
我们需要server.c 和 client.c
2. server.c
/*
* socket
* bind
* listen
* accept
* send/recv
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <signal.h>
#define SERVER_PORT 8888
#define BACKLOG 10
int main(int argc, char **argv)
{
int server;
int client;
struct sockaddr_in server_addr;
struct sockaddr_in client_addr;
int ret;
int server_recv;
int addr_len;
unsigned char recvbuf[1000];
int client_num = -1;
//signal(SIGCHLD, SIG_IGN); /* 处理僵死进程 */
/* 句柄 */
server = socket(AF_INET, SOCK_STREAM, 0);
if (server == -1){
printf("soket error!\n");
return -1;
}
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
server_addr.sin_addr.s_addr = INADDR_ANY;
memset(server_addr.sin_zero, 0, 8);
/* 将文件句柄绑定ip和端口*/
ret = bind(server, (const struct sockaddr *)&server_addr,
sizeof(struct sockaddr));
if (ret == -1){
printf("bind error!\n");
return -1;
}
/* 开始检测 */
ret = listen(server, BACKLOG);
if (ret == -1){
printf("listen error!\n");
return -1;
}
while (1) {
/* 等待客户端连接*/
addr_len = sizeof(struct sockaddr);
client = accept(server, (struct sockaddr *)&client_addr, &addr_len);
if (client != -1){
client_num++; /* 统计客户端*/
printf("get connect form client %d : %s \n", client_num,
inet_ntoa(client_addr.sin_addr));
/* 支持多个客户端连接,对每个连接创建一个子进程 */
if (!fork()){
/* 子进程 */
while (1){
/* 接受客户端发来的数据 */
server_recv = recv(client, recvbuf, 999, 0);
if (server_recv <= 0){
close(client);
return -1;
} else {
recvbuf[server_recv]= '\0';
printf("get msg form %d : %s\n", client_num, recvbuf);
}
}
}
}
}
close(server);
return 0;
}
3. client.c
/*
* socket
* connect
* send/recv
*/
#include <stdio.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <string.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
#define SERVER_PORT 8888 /* 端口和server.c 保持一致 */
int main(int argc, char **argv)
{
int client;
struct sockaddr_in server_addr;
int ret;
unsigned char sendbuf[1000];
int client_send;
if (argc != 2){
printf("Usage: %s <server_ip>\n", argv[0]);
return -1;
}
/* 创建句柄 */
client = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
server_addr.sin_family = AF_INET;
server_addr.sin_port = htons(SERVER_PORT);
//server_addr.sin_addr.s_addr = INADDR_ANY;
if (inet_aton(argv[1], &server_addr.sin_addr) == 0){
printf("invalid server_ip\n");
return -1;
}
memset(server_addr.sin_zero, 0, 8);
/* 连接服务器 */
ret = connect(client, (const struct sockaddr *)&server_addr,
sizeof(struct sockaddr));
if (ret == -1){
printf("connect error!\n");
return -1;
}
while (1){
if (fgets(sendbuf, 999, stdin)){
/* 发送数据给服务器 */
client_send = send(client, sendbuf, strlen(sendbuf), 0);
if (client_send <= 0){
close(client);
return -1;
}
}
}
return 0;
}
4. 实验
整体流程:client1和client2和server进行通讯,然后ps -a 查看进程。(开4个窗口)