// server.c
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
// 通过命令行参数传入绑定端口号
int main(int argc, char *argv[])
{
if (argc < 2)
{
fprintf(stderr, "Usage: %s <port>.\n", argv[0]);
return 0;
}
// 1. 创建socket
// socket 第一个参数:域,本地通信(PF_UNIX, PF_LOCAL, PF_FILE,
// AF_UNIX, AF_LOCAL, AF_FILE); 网络通信(PF_INET, PF_INET6,
// AF_INET, AF_INET6);
// 第二个参数:通信类型, SOCK_STREAM, SOCK_DGRAM
// 第三个参数:已经废弃
int sock_fd = socket(PF_INET, SOCK_STREAM, 0);
if (sock_fd == -1)
{
perror("create socket is failed");
return -1;
}
// 2. 绑定主机地址
// man in.h
// struct sockaddr_in
// {
// sa_family_t sin_family; // AF_INET
// in_port_t sin_port; // Port
// struct in_addr sin_addr; // IP Address
// };
// struct in_addr { in_addr_t s_addr };
struct sockaddr_in addrServer;
memset(&addrServer, 0, sizeof(addrServer));
addrServer.sin_family = PF_INET;
addrServer.sin_addr.s_addr = htonl(INADDR_ANY);
addrServer.sin_port = htons(atoi(argv[1]));
// 绑定
if (bind(sock_fd, (const struct sockaddr *)&addrServer,
sizeof(addrServer)) == -1)
{
perror("bind socket is failed");
close(sock_fd), sock_fd = -1;
return -2;
}
// 3. 监听
listen(sock_fd, 5);
// 4. 阻塞等待客户端连接
while (1)
{
struct sockaddr_in addrClient;
memset(&addrClient, 0, sizeof(addrClient));
socklen_t addrLength = sizeof(addrClient);
int sock_fd_conn = 0;
sock_fd_conn = accept(sock_fd, (struct sockaddr *)&addrClient,
&addrLength);
if (sock_fd_conn == -1)
continue;
printf("client connected: %s\n", inet_ntoa(addrClient.sin_addr));
char strRecv[256] = {0};
if (recv(sock_fd_conn, strRecv, 256, 0) == -1)
{
fprintf(stderr, "recv is failed.\n");
close(sock_fd_conn), sock_fd_conn = -1;
continue;
}
printf("Client: %s\n", strRecv);
char strSend[256] = {0};
sprintf(strSend, "Hello, Client: %s\n",
inet_ntoa(addrClient.sin_addr));
if (send(sock_fd_conn, strSend,
strlen(strSend) + sizeof(char), 0) == -1)
{
fprintf(stderr, "send is filed.\n");
close(sock_fd_conn), sock_fd_conn = -1;
continue;
}
// 关闭连接fd
close(sock_fd_conn), sock_fd_conn = -1;
}
// 5. 关闭socket
close(sock_fd), sock_fd = -1;
return 0;
}
// client.c
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <netinet/in.h>
int main(int argc, char *argv[])
{
if (argc < 3)
{
fprintf(stderr, "Usage: %s <IPAddress> <Port>", argv[0]);
return 0;
}
// 1. 创建socket
int sock_fd = socket(AF_INET, SOCK_STREAM, 0);
if (sock_fd == -1)
{
perror("create socket fail");
return -1;
}
// 2. 准备服务器地址
struct sockaddr_in addrServer;
memset(&addrServer, 0, sizeof(addrServer));
addrServer.sin_family = AF_INET;
addrServer.sin_port = htons(atoi(argv[2]));
inet_aton(argv[1], &addrServer.sin_addr);
// 3. 连接到服务器
int nRet = 0;
nRet = connect(sock_fd, (struct sockaddr *)&addrServer,
sizeof(addrServer));
if (nRet == -1)
{
perror("connect fail");
close(sock_fd), sock_fd = -1;
return -2;
}
// 收发数据
const char *strSendData = "Hello, Server";
send(sock_fd, strSendData, strlen(strSendData) + 1, 0);
char strRecvData[256] = {0};
recv(sock_fd, strRecvData, 256, 0);
fprintf(stdout, "Server: %s\n", strRecvData);
// 关闭连接fd
close(sock_fd), sock_fd = -1;
return 0;
}
两个文件各自编译:
gcc server.c -o server -Wall
gcc client.c -o client -Wall
先运行./server 8888
再运行./client 127.0.0.1 8888
8888 是约定端口号必须对应一致,可以为其它无符号整形。
server 端的运行结果:
[SuYH@localhost server]$ ./server 8888
client connected:127.0.0.1
Client: Hello, Server
client 端的运行结果:
[SuYH@localhost client]$ ./client 127.0.0.1 8888
Server: Hello, Client: 127.0.0.1
[SuYH@localhostclient]$