在C语言中实现网络编程的客户端和服务器,主要涉及TCP/IP协议的使用,以下是对相关概念、代码实现以及常见问题解答的详细阐述。
一、基本概念

1、套接字(Socket):用于描述IP地址和端口,是通信链的句柄,可以实现不同虚拟机或计算机之间的通信。
2、TCP协议:一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。
二、服务器端流程
1、初始化并监听:服务器首先调用socket()函数创建套接字,然后使用bind()函数将套接字与指定的IP地址和端口号绑定,接着调用listen()函数声明当前文件描述符为服务器的文件描述符,最后调用accept()函数阻塞等待客户端连接。
2、建立连接:当客户端发起连接请求时,服务器通过三次握手建立连接。
3、数据传输:连接建立后,服务器从accept()函数返回,并立即调用read()函数读取数据,客户端则调用write()函数发送请求。
4、断开连接:客户端没有更多请求时调用close()函数关闭连接,服务器收到FIN后回应ACK,并关闭连接。
三、客户端流程
1、连接服务器:客户端调用socket()函数创建套接字,然后使用connect()函数向服务器发起连接请求。
2、数据传输:连接建立后,客户端调用write()函数发送请求,服务器收到请求后处理并返回应答,客户端调用read()函数接收应答。
3、断开连接:客户端完成数据传输后,调用close()函数关闭套接字,结束通信。
四、示例代码

1. 客户端代码(client.c)
#include <netdb.h>
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/socket.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr
void func(int sockfd) {
char buff[MAX];
int n;
for (;;) {
bzero(buff, sizeof(buff));
printf("Enter the string : ");
n = 0;
while ((buff[n++] = getchar()) != '
');
write(sockfd, buff, sizeof(buff));
bzero(buff, sizeof(buff));
read(sockfd, buff, sizeof(buff));
printf("From Server : %s", buff);
if ((strncmp(buff, "exit", 4)) == 0) {
printf("Client Exit...
");
break;
}
}
}
int main(int argc, char const *argv[]){
int sockfd; //连接符
struct sockaddr_in servaddr;
// 套接字创建
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...
");
exit(0);
} else
printf("Socket successfully created..
");
bzero(&servaddr, sizeof(servaddr)); //初始化结构体
//分配IP,端口
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = inet_addr("127.0.0.1");
servaddr.sin_port = htons(PORT);
//连接服务器,如果非0,则连接失败
if (connect(sockfd, (SA*)&servaddr, sizeof(servaddr)) != 0) {
printf("connection with the server failed...
");
exit(0);
} else
printf("connected to the server..
");
func(sockfd);
// 关闭套接字
close(sockfd);
}2. 服务端代码(server.c)
#include <netdb.h>
#include <netinet/in.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#define MAX 80
#define PORT 8080
#define SA struct sockaddr
void func(int sockfd) {
char buff[MAX];
int n;
for (;;) {
bzero(buff, sizeof(buff));
read(sockfd, buff, sizeof(buff));
printf("From client : %s", buff);
bzero(buff, sizeof(buff));
printf("Enter the string : ");
n = 0;
while ((buff[n++] = getchar()) != '
');
write(sockfd, buff, sizeof(buff));
if ((strncmp(buff, "exit", 4)) == 0) {
printf("Server Exit...
");
break;
}
}
}
int main() {
int sockfd, connfd; //连接符
struct sockaddr_in servaddr, cliaddr;
// 套接字创建
sockfd = socket(AF_INET, SOCK_STREAM, 0);
if (sockfd == -1) {
printf("socket creation failed...
");
exit(0);
} else
printf("Socket successfully created..
");
bzero(&servaddr, sizeof(servaddr)); //初始化结构体
//分配IP,端口
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
servaddr.sin_port = htons(PORT);
//绑定套接字到指定IP和端口
if ((bind(sockfd, (SA*)&servaddr, sizeof(servaddr))) != 0) {
printf("socket bind failed...
");
exit(0);
} else
printf("Socket successfully binded..
");
//开始监听,等待连接请求
if ((listen(sockfd, 5)) != 0) {
printf("Listen failed...
");
exit(0);
} else
printf("Server listening..
");
//接受客户端连接请求
while (1) {
connfd = accept(sockfd, (SA*)&cliaddr, &cliaddr);
if (connfd < 0) {
printf("server acccept failed...
");
exit(0);
} else
printf("server acccept the client...
");
//调用func函数进行数据交互
func(connfd);
//关闭套接字连接
close(connfd);
}
}五、相关问题与解答栏目
问题1:为什么客户端通常不需要绑定端口?
答:在大多数情况下,客户端不需要绑定端口号,客户端通常只是连接到服务器的指定IP地址和端口号来发送请求或接收响应,客户端操作系统会为客户端分配一个临时的端口号来进行通信,这个端口号是由操作系统自动选择的,客户端无需手动指定,在某些特殊场景下(如P2P应用、多客户端连接等),客户端可能需要明确绑定端口。
问题2:如何让外部设备访问本地服务器上的服务?
答:要让外部设备能够访问本地服务器上的服务,可以将服务器绑定的IP地址设置为0.0.0.0(表示监听所有网络接口上的请求)或者服务器的真实IP地址,确保防火墙设置允许外部访问该端口。
小伙伴们,上文介绍了“c网络编程客户端服务器”的内容,你了解清楚吗?希望对你有所帮助,任何问题可以给我留言,让我们下期再见吧。
文章来源网络,作者:运维,如若转载,请注明出处:https://shuyeidc.com/wp/1425.html<
