LV.8 D7 实现TCP通信 学习笔记

文章详细介绍了如何使用socket函数在IPv4环境下建立TCP通信,包括设置通信域、套接字类型、协议,以及使用bind、listen、accept等函数处理客户端连接。服务器端代码接收并打印客户端发送的数据,客户端则持续发送用户输入的信息。同时,给出了用于编译的Makefile。
摘要由CSDN通过智能技术生成

socket函数 与 通信域

#include <sys/types.h>
#include <sys/socket.h>
int socket(int domain, int type, int protocol);
//-domain: 指定通信域(通信地址族);
//-type: 指定套接字类型;
//-protocol: 指定协议;

参数: 

 

套接字类型与协议

-type: 指定套接字类型

        TCP唯一对应流式套接字,所以选择SOCK_STREAM(数据报套接字:SOCK_DGRAM)

-protocol: 指定协议

        流式套接字唯一对应TCP,所以无需要指定协议,设为0即可

bind函数 与 通信结构体

#include <sys/types.h>
#include <sys/socket.h>
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地址 */
};
//通用地址族结构体
struct sockaddr {
               sa_family_t sa_family;
               char        sa_data[14];
           }
//实例:为套接字fd绑定通信结构体addr
addr.sin_family = AF_INET;
addr.sin_port = htons(5001);//主机字节序转网络字节序,16位数据
addr.sin_addr.s_addr = 0;
bind(fd, (struct sockaddr *)&addr, sizeof(addr) );

listen函数 与 accept函数

/*监听套接字*/
int listen(int sockfd, int backlog);
/*处理客户端发起的连接,生成新的套接字*/
int accept(int sockfd, struct sockaddr *addr, socklen_t *addrlen);
-sockfd: 函数socket生成的套接字
-addr(传出参数):客户端的地址族信息
-addrlen:地址族结构体的长度

注意:accept()函数是一个阻塞函数。

作业:实现TCP通信代码,并用Makefile进行编译

服务器端:

//server.c         //服务器端 
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>

#define BACKLOG 5

int main(int argc, char *argv[])
{
	int fd, newfd, ret;
	char buf[BUFSIZ] = {}; //BUFSIZ 8142
	struct sockaddr_in addr;
	
	if(argc < 3){
		fprintf(stderr, "%s<addr><port>\n", argv[0]);
		exit(0);
	}

	/*创建套接字*/
	fd = socket(AF_INET, SOCK_STREAM, 0);//fd是监听文件描述符
	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(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);//newfd是通信文件描述符
	if(newfd < 0){
		perror("accept");
		exit(0);
	}
	while(1){
		memset(buf, 0, BUFSIZ);
		ret = read(newfd, buf, BUFSIZ);
		if(ret < 0)
		{
			perror("read");
			exit(0);
		}
		else if(ret == 0)
			break;
		else
			printf("buf = %s\n", buf);
	}
	close(newfd);
	close(fd);
	return 0;
}

 客户端:

//client.c     //客户端
#include <stdio.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <stdlib.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>

#define BACKLOG 5

int main(int argc, char *argv[])
{
	int fd;
	struct sockaddr_in addr;
	char buf[BUFSIZ] = {};

	if(argc < 3){
		fprintf(stderr, "%s<addr><port>\n", argv[0]);
		exit(0);
	}

	/*创建套接字*/
	fd = socket(AF_INET, SOCK_STREAM, 0);//fd是通信文件描述符
	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){
		perror("connect");
		exit(0);
	}
	while(1){
		printf("Input->");
		fgets(buf, BUFSIZ, stdin);
		write(fd, buf, strlen(buf) );
	}
	close(fd);
	return 0;
}

Makefile: 

CC=gcc
CFLAGS=-Wall
all:client server

clean:
	rm client server

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值