#include
#include
int socket(int domain, int type, int protocol);
-domain: 指定通信域(通信地址族);
-type: 指定套接字类型;
-protocol: 指定协议;
套接字类型与协议
-type: 指定套接字类型
TCP唯一对应流式套接字,所以选择SOCK_STREAM(数据报套接字:SOCK_DGRAM)
-protocol: 指定协议
流式套接字唯一对应TCP,所以无需要指定协议,设为0即可

bind函数与通信结构体
int bind(int sockfd, const struct sockaddr *addr, socklen_t addrlen);
-sockfd:socket函数生成的套接字
-addr:通信结构体
-addrlen:通信结构体的长度

IPv4地址族结构体
struct sockaddr_in {
sa_family_t sin_family; /* 地址族: AF_INET */
in_port_t sin_port; /* 网络字节序的端口号 */
struct in_addr sin_addr; /*IP地址结构体 */
};
/* IP地址结构体 */
struct in_addr {
uint32_t s_addr; /* 网络字节序的IP地址 */
};
服务端
- #include
- #include
- #include
- #include
- #include
- #include
-
- #define PORT 5001
- #define BACKLOG 5
-
- int main(int argc, char *argv[])
- {
- int fd, newfd;
- char buf[BUFSIZ] = {}; //BUFSIZ 8142
- struct sockaddr_in addr;
- /*创建套接字*/
- fd = socket(AF_INET, SOCK_STREAM, 0);
- if(fd < 0){
- perror("socket");
- exit(0);
- }
- addr.sin_family = AF_INET;
- addr.sin_port = htons(PORT);
- addr.sin_addr.s_addr = 0;
- /*绑定通信结构体*/
- if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){
- perror("bind");
- exit(0);
- }
- /*设置套接字为监听模式*/
- if(listen(fd, BACKLOG) == -1){
- perror("listen");
- exit(0);
- }
- /*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/
- newfd = accept(fd, NULL, NULL);
- if(newfd < 0){
- perror("accept");
- exit(0);
- }
- printf("BUFSIZ = %d\n", BUFSIZ);
- read(newfd, buf, BUFSIZ);
- printf("buf = %s\n", buf);
- close(fd);
- return 0;
- }
客户端
- #include
- #include
- #include
- #include
- #include
- #include
-
- #define PORT 5001
- #define BACKLOG 5
- #define STR "Hello World!"
-
- int main(int argc, char *argv[])
- {
- int fd;
- struct sockaddr_in addr;
- /*创建套接字*/
- fd = socket(AF_INET, SOCK_STREAM, 0);
- if(fd < 0){
- perror("socket");
- exit(0);
- }
- addr.sin_family = AF_INET;
- addr.sin_port = htons(PORT);
- addr.sin_addr.s_addr = inet_addr("127.0.0.1");
- /*向服务端发起连接请求*/
- if(connect(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){
- perror("connect");
- exit(0);
- }
- write(fd, STR, sizeof(STR) );
- printf("STR = %s\n", STR);
- close(fd);
- return 0;
- }
服务端
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #define BACKLOG 5 //BACKLOG为5,表示服务器端可以排队的最大客户端连接数
-
- int main(int argc, char *argv[])
- {
- int fd, newfd, ret;
- char buf[BUFSIZ] = {}; //BUFSIZ 8142 用于存储从客户端读取的数据
- struct sockaddr_in addr; //存储服务器的地址信息
-
- if(argc < 3){ //检查命令行参数的数量是否小于3,如果是,则打印错误信息并退出程序。这是因为服务器需要两个命令行参数:服务器的IP地址和端口号。
- fprintf(stderr, "%s
\n" , argv[0]); - exit(0);
- }
-
- /*创建套接字*/
- fd = socket(AF_INET, SOCK_STREAM, 0); //创建一个新的套接字
- if(fd < 0){ //AF_INET表示使用IPv4协议,SOCK_STREAM表示使用TCP协议
- perror("socket");
- exit(0);
- }
- addr.sin_family = AF_INET; //使用IPv4协议
- addr.sin_port = htons( atoi(argv[2]) ); //将命令行参数中的端口号转换为整数,并使用htons函数将其转换为网络字节序,然后设置到addr结构体中的sin_port字段。
- if ( inet_aton(argv[1], &addr.sin_addr) == 0) { //将命令行参数中的IP地址转换为网络字节序并设置到addr结构体中的sin_addr字段。如果转换失败,则打印错误信息并退出程序。
- fprintf(stderr, "Invalid address\n");
- exit(EXIT_FAILURE);
- }
-
- /*绑定通信结构体*/
- if(bind(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){ //调用bind函数将套接字fd绑定到地址信息addr
- perror("bind");
- exit(0);
- }
- /*设置套接字为监听模式*/
- if(listen(fd, BACKLOG) == -1){ //用listen函数将套接字fd设置为监听模式,并设置最大客户端连接数为BACKLOG
- perror("listen");
- exit(0);
- }
- /*接受客户端的连接请求,生成新的用于和客户端通信的套接字*/
- newfd = accept(fd, NULL, NULL); //调用accept函数接受客户端的连接请求,并返回一个新的套接字描述符newfd用于和客户端通信
- if(newfd < 0){
- perror("accept");
- exit(0);
- }
- while(1){
- memset(buf, 0, BUFSIZ); //调用memset函数将buf数组中的所有元素都设置为0
- ret = read(newfd, buf, BUFSIZ); //调用read函数从客户端套接字newfd读取数据,并将数据存储到buf数组中。read函数返回读取到的字节数,并将其存储到ret变量中
- if(ret < 0) //如果read函数返回值小于0,表示读取数据失败
- {
- perror("read");
- exit(0);
- }
- else if(ret == 0) //如果read函数返回值等于0,表示客户端已经关闭了连接
- break;
- else
- printf("buf = %s\n", buf);
- }
- close(newfd); //关闭客户端套接字和服务器套接字
- close(fd);
- return 0;
- }
-
客户端
- #include
- #include
- #include
- #include
- #include
- #include
- #include
-
- #define BACKLOG 5
-
- int main(int argc, char *argv[])
- {
- int fd;
- struct sockaddr_in addr;
- char buf[BUFSIZ] = {};
-
- if(argc < 3){
- fprintf(stderr, "%s
\n" , argv[0]); - exit(0);
- }
-
- /*创建套接字*/
- fd = socket(AF_INET, SOCK_STREAM, 0);
- if(fd < 0){
- perror("socket");
- exit(0);
- }
-
- addr.sin_family = AF_INET;
- addr.sin_port = htons( atoi(argv[2]) );
- if ( inet_aton(argv[1], &addr.sin_addr) == 0) {
- fprintf(stderr, "Invalid address\n");
- exit(EXIT_FAILURE);
- }
-
- /*向服务端发起连接请求*/
- if(connect(fd, (struct sockaddr *)&addr, sizeof(addr) ) == -1){ //调用connect函数向服务器发起连接请求
- perror("connect");
- exit(0);
- }
- while(1){
- printf("Input->");
- fgets(buf, BUFSIZ, stdin); //调用fgets函数从标准输入读取一行数据,并将其存储到buf数组中。
- write(fd, buf, strlen(buf) ); //调用write函数将buf数组中的数据发送给服务器。
- }
- close(fd);
- return 0;
- }
-
makefile
CC=gcc
CFLAGS=-Wall
all:client serverclean:
rm client server