tcp socket

本文介绍了TCP/IP通信中服务端和客户端的实现,展示了使用阻塞模式的多线程服务器如何处理连接。阻塞模式适合并发量小、大数据量的场景,如文件服务器。非阻塞模式常用于高并发、小数据量的场景,如聊天室,以避免过多线程影响效率。客户端通常不采用非阻塞模式。
摘要由CSDN通过智能技术生成
//server.c
#include <stdio.h>
#include <unistd.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <arpa/inet.h>
#include <string.h>

#define PORT 4321
#define MAX_QUE_CONN_NM 5
#define MAXLEN 1024
#define RET_OK 1
#define RET_ERROR 0

int socket_listen()
{
	int sockfd;
	struct sockaddr_in server_sockaddr;

	if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
	{
		return RET_ERROR;
	}

	bzero(&server_sockaddr, sizeof(server_sockaddr));
	server_sockaddr.sin_family = AF_INET;
	server_sockaddr.sin_port = htons(PORT);
	server_sockaddr.sin_addr.s_addr = htonl(INADDR_ANY);

	if (bind(sockfd, (struct sockaddr*)(&server_sockaddr), sizeof(struct sockaddr)) == -1)
	{
		return RET_ERROR;
	}

	if (listen(sockfd, MAX_QUE_CONN_NM) == -1)
	{
		return RET_ERROR;
	}
	return sockfd;
}

int server_socket_listen()
{
	int sin_size;
	int recvbytes;
	int sockfd;
	int client_fd;
	char server_buf[MAXLEN];
	int sendbytes;
	struct sockaddr_in client_sockaddr;

	sockfd = socket_listen();
	if (sockfd == RET_ERROR)
	{
		return RET_ERROR;
	}

	while (1)
	{
		sin_size = sizeof(struct sockaddr_in);
		if ((client_fd = accept(sockfd, (struct sockaddr*) & client_sockaddr, &sin_size)) == -1)
		{
			return RET_ERROR;
		}

		memset(server_buf, 0, sizeof(server_buf));
		recvbytes = recv(client_fd, server_buf, MAXLEN, 0);
		if (recvbytes < 0)
		{
			return RET_ERROR;
		}
	}
	close(sockfd);
	return RET_OK;
}

int main()
{
	server_socket_listen();

	return 0;
}
//client.c
#include <sys/types.h>
#include <sys/socket.h>
#include <stdio.h>
#include <stdlib.h>
#include <errno.h>
#include <string.h>
#include <unistd.h>
#include <netinet/in.h>
#define PORT 4321                     
#define BUFFER_SIZE 1024              

int main(int argc,char *argv[])
{
    int sockfd;                                                            
    int sendbytes;                                                        
    char buf[BUFFER_SIZE];                                               
    struct hostent *host;                                                
    struct sockaddr_in server_addr;                                  
                                                                                                         
    if ((sockfd = socket(AF_INET, SOCK_STREAM, 0)) == -1)
    {
        perror("socket");
        exit(1);
    }
    printf("socket created\n");
    bzero(&server_addr, sizeof(server_addr));

    server_addr.sin_family = AF_INET;
    server_addr.sin_port = htons(PORT);
    server_addr.sin_addr.s_addr = inet_addr("127.0.0.1");        
        
    if (connect(sockfd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1)
    {
        perror("connect");
        exit(1);
    }

    memset(buf, 0, sizeof(buf));
    sprintf(buf, "%s", "hello");

    if ((sendbytes = send(sockfd, buf, strlen(buf), 0)) == -1)
    {
        perror("send");
        exit(1);
    }
        
    memset(buf, 0, sizeof(buf));
    recv(sockfd, buf, 1024, 0);
    printf("recv:%s\n", buf);
    close(sockfd);
    return 0;
}

阻塞模式:常见的通信模型为多线程模型,服务端accept之后,对每个socket创建一个线程去recv。

逻辑上简单,适用于并发量小(客户端数目小),连续传输大数据量的情况下,比如文件服务器。还有就是客户端recv服务器消息的时候也经常用,因为客户端就一个socket,用阻塞模式不影响效率,而且编程逻辑上要简单的多。

 

非阻塞模式,常见的通信模型为select模型和IOCP模型。适用于高并发,数据量小的情况,比如聊天室。客户端多的情况下,如果采用阻塞模式,需要开很多线程,影响效率。另外,客户端一般不采用非阻塞模式。

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值