Linux-TCP/IP socket编程

服务器

    1、建立连接
    socket(),分配文件描述符,即监听套接字
    bind(),将套接字与本地IP地址和端口绑定
    listen(),监听特定端口,可设置监听连接最大个数
    accept(),阻塞等待客户端连接
    2、数据收发
    read()/recv()阻塞等待客户端发送数据,收到数据后从read()/recv()返回数据和数据数量
    write()/send()将处理结果发送给客户端,然后继续调用read()/recv()等待客户端请求
    3、关闭连接
    当read()/recv()返回0的时候,说明客户端发来FIN数据包,即关闭连接,调用close()关闭连接套接字和监听套接字
    当客户端调用close()关闭连接套接字时也会受到客户端发开的断开连接请求

客户端

    1、建立连接
    socket(),分配文件描述符
    connect(),向服务器发送建立连接请求
    2、数据收发
    write()/send(),将数据发送给服务器
    read()/recv(),阻塞等待服务器应答回复数据
    3、关闭连接
    当没有数据发送的时候,调用close()关闭连接套接字,即关闭连接,向服务器发送FIN数据报
    或者write()/send()发送0字节给服务器表示断开连接

TCP通信过程

    图片转载自:https://blog.csdn.net/upupday19/article/details/78916142

示例代码

    头文件:std.h

#ifndef _STD_
#define _STD_

// 头文件 //
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
#include <stdlib.h>
#include <stdio.h>
#include <dirent.h>
#include <sys/types.h>
#include <grp.h>
#include <string.h>
#include <time.h>
#include <string.h>
#include <errno.h>
//tcp//
#include <sys/types.h>  
#include <sys/socket.h>
#include <netinet/in.h>
#include <netinet/ip.h> 
#include <arpa/inet.h>

//错误提示//
#define err_exit(function)					\
		do {								\
			fprintf(stderr, "in %s at %s %d:\n%s : %s\n", __FUNCTION__, __FILE__, __LINE__ - 1, function, strerror(errno)); \
			exit(EXIT_FAILURE);				\
		} while(0)

#endif

    服务器代码:test_tcp_server.c

//服务器端//
#include "std.h"

int main(void)
{
	//定义服务器监听套接字和连接套接字
	int listenfd = -1;
	int connfd = -1;
	struct sockaddr_in server, client;//定义服务器对应的套接字地址
	char buf[BUFSIZ];
	int ret=-1;

	//初始化套接字地址结构体
	memset(&server, 0, sizeof(server));
	server.sin_family = AF_INET;//IPv4
	server.sin_port = htons(888);//设置监听端口
	//server.sin_addr.s_addr = inet_addr("192.168.1.50");//谁的地址?
	//server.sin_addr.s_addr = inet_addr("0");//?
	//server.sin_addr.s_addr = INADDR_ANY;//?
	server.sin_addr.s_addr = htonl(INADDR_ANY);//INADDR_ANY接收任意IP的连接请求
	
	//创建套接字
	if (0 > (listenfd = socket(AF_INET, SOCK_STREAM, 0)))
		err_exit("socket");

	//绑定套接字和本地IP地址和端口
	if (0 > bind(listenfd, (struct sockaddr *)&server, sizeof(server)))
		err_exit("bind");

	//设置listen_fd为监听描述符
	listen(listenfd, 1024);//1024为最大连接个数
	printf("listen...\n");

	//accept阻塞等待客户端请求
	memset(&client, 0, sizeof(client));
	socklen_t len = sizeof(client);
	if (0 > (connfd = accept(listenfd, (struct sockaddr *)&client, &len)))
		err_exit("accept");
	printf("client's ip is: %s, port is: %d\n", inet_ntoa(client.sin_addr), ntohs(client.sin_port));
	fflush(stdout);

	while(1)
	{
		//读取客户端发来的信息
		memset(buf, 0, sizeof(buf));
		if (0 > (ret = recv(connfd, buf, BUFSIZ, 0)))
			err_exit("recv");
		else if (0 == ret)//客户端关闭连接请求断开或发送0字节数据会走这里
		{
			printf("client quit!\n");
			//关闭连接套接字
			close(connfd);
			//关闭监听套接字
			close(listenfd);
			exit(0);
		}
		buf[ret] = '\0';
		printf("recv client: %s\n", buf);
		//向客户端发送信息
		send(connfd, "ok", sizeof("ok"), 0);		
	}
}

    客户端代码:test_tcp_client.c

//客户端//
#include "std.h"

int main(void)
{
	int connfd = -1;//定义客户端套接字
	struct sockaddr_in server;//定义服务器的套接字地址
	char buf[BUFSIZ];//stdlib.h定义BUFSIZ=8192
	int ret=-1;

	//初始化服务器套接字地址
	memset(&server, 0, sizeof(server));
	server.sin_family = AF_INET;//IPv4
	server.sin_port = htons(888);//服务器端口
	server.sin_addr.s_addr = inet_addr("192.168.1.50");//服务器IP地址

	//创建套接字
	if (0 > (connfd = socket(AF_INET, SOCK_STREAM, 0)))
		err_exit("socket");

	//发送连接请求
	if (0 > connect(connfd, (struct sockaddr *)&server, sizeof(server)))
		err_exit("connect");
	printf("connect success!\n");
	
	//输入并向服务器发送字符串
	memset(buf, 0, sizeof(buf));
	fgets(buf, sizeof(buf), stdin);
	send(connfd, buf, strlen(buf)-1, 0);//-1目的是去除\n字符

	//从服务器接收数据
	if (0 > (ret = recv(connfd, buf, BUFSIZ, 0)))
		err_exit("recv");
	else if (0 == ret) {
		printf("server quit!\n");
		close(connfd);
	}
	buf[ret] = '\0';
	printf("recv server: %s\n", buf);

	//memset(buf, 0, sizeof(buf));
	fgets(buf, sizeof(buf), stdin);
	send(connfd, buf, strlen(buf)-1, 0);

	close(connfd);
	exit(0);
}

扩展

    select,poll,epoll实现机制区别:https://www.cnblogs.com/aspirant/p/9166944.html

猜你喜欢

转载自blog.csdn.net/TSZ0000/article/details/83345049