Linux TCP客户端、服务器编程模型及实例

Linux TCP客户端、服务器编程模型及实例


服务器模型:
1、绑定IPv4的地址(INADDR_ANY)和端口号(8888)
int listenfd, sockfd, opt = 1;
struct sockaddr_in server, client;
新建socket
listenfd = socket(AF_INET, SOCK_STREAM, 0);
if(listenfd < 0){
perror("Create socket fail.");
return -1;
}
设置地址可重用功能,防止异常退出无法短时间打开server
if((ret = setsockopt(listenfd, SOL_SOCKET, SO_REUSEADDR, &opt, sizeof(opt))) < 0)
{
    perror("Error, set socket reuse addr failed");
  return -1;
}
bzero(&server, sizeof(server));
server.sin_family = AF_INET;
server.sin_port   = htons(8888);
server.sin_addr.s_addr  = htonl(INADDR_ANY);
2、将套接字转换成监听套接字
len = sizeof(struct sockaddr);
if(bind(listenfd, (struct sockaddr *)&server, len)<0){
perror("bind error.");
    return -1;
}
listen(listenfd, MAX_LISTEN_QUE);
3、等待客户端连接
sockfd = accept(listenfd, (struct sockaddr *)&client, &len);
if(sockfd < 0)
{
perror("accept error.");
return -1;
}
4、读取客户端数据
read(sockfd,buf,100);
printf("%s\n",buf);
5、写据给客户端
time_now = time(NULL);
bzero(&buf,100);
strcpy(buf,(char *)ctime(&time_now));
printf("time:%s\n",buf);
write(sockfd,buf,strlen(buf));
6、关闭套接字
close(sockfd);
close(listenfd);

实例代码:

头文件apue.h

#include<stdio.h>
#include<stdlib.h>
#include<errno.h>
#include<string.h>
#include<strings.h>
#include<time.h>

#include<sys/socket.h>
#include<sys/types.h>
#include<netinet/in.h>
#include<arpa/inet.h> //inet

源文件3.c

/*************************************************************************
    > File Name: 3.c
    > Created Time: 2016年12月01日 星期四 10时53分36秒
 ************************************************************************/
/*
 *this is time server
 * */

#include"apue.h"
#define MAX_LISTEN 10
int main(int argc,char *argv[])
{
	int listenfd,sockfd,opt = 1;
	struct sockaddr_in server,client;
	int len;
	time_t time_now;
	char buf[100];

	listenfd = socket(AF_INET,SOCK_STREAM,0);
	if(listenfd<0)
	{
		perror("create socket failed\n");
		return -1;
	}

	if(setsockopt(listenfd,SOL_SOCKET,SO_REUSEADDR,&opt,sizeof(opt))<0)
	{
		perror("set socket reuse addr failed\n");
		return -1;
	}
	
	bzero(&server,sizeof(server));
	server.sin_family = AF_INET;
	server.sin_port = htons(8888);
	server.sin_addr.s_addr = htonl(INADDR_ANY);//代表该主机上的所有IP地址,如果机器上有多个网卡或者虚拟机的话,若不使用此方法容易出错

	len = sizeof(struct sockaddr);
	if(bind(listenfd,(struct sockaddr *)&server,len)<0)
	{
		perror("bind error\n");
		return -1;
	}
	
	listen(listenfd,MAX_LISTEN);//可以连接的最大数据
	
	while(1) //迭代服务器,同时不能连接多个客户端,当一个客户端关闭后就可以重新连接第二个客户端
	{
	sockfd = accept(listenfd,(struct sockaddr *)&client,&len);//sockaddr 和sockaddr_in可以相互转化的
	if(sockfd<0)
	{
		perror("accept error\n");
		return -1;
	}
	
	read(sockfd,buf,100);
	printf("%s\n",buf);

	time_now = time(NULL);
	bzero(&buf,100);
	strcpy(buf,(char *)ctime(&time_now));
	printf("time:%s\n",buf);
	write(sockfd,buf,strlen(buf));
	printf("sockfd:%d\n",sockfd);	
	close(sockfd);
	}
	
	close(listenfd);
	return 0;
}

客户端模型:

1、创建一个IPv4(AF_INET)的字节流(SOCK_STREAM)套接字
int sockfd;
struct sockaddr_in server_ip;
if((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)
{
    perror("socket error\n");
    return -1;
}
2、连接到IP地址为(192.168.1.108、127.0.0.1),端口号为8888的服务器
 bzero(&server_ip,sizeof(server_ip));
//equal to memset()
server_ip.sin_family  =AF_INET;
server_ip.sin_addr.s_addr = inet_addr("127.0.0.1");
server_ip.sin_port = htons(5678);


if(connect(sockfd,(struct sockaddr*)&server_ip,sizeof(server_ip))<0)
{
    perror("connect error\n");
    return 0;
}
3、写一个数据到服务器
strcpy(buf,(char *)"I am client");
if(write(sockfd,buf,strlen(buf))<0)
{
    printf("error,write error\n");
    return -1;
}
4、接收服务器传回来的数据并显示到标准输出
bytes = read(sockfd,buf,100);
if(bytes<0)
{
    printf("error,read failed\n");
    return -1;
}
5、关闭套接字
close(sockfd);

实例代码:

头文件同上;

源文件2.c

/*************************************************************************
    > File Name: 2.c
    > Created Time: 2016年12月01日 星期四 09时52分46秒
 ************************************************************************/
/*
 *this is client to get server time
 * */
#include"apue.h"

int main(int agtc,char *argv[])
{
	int sockfd;
	struct sockaddr_in server_ip;
	char buf[100];
	int bytes;
	if((sockfd = socket(AF_INET,SOCK_STREAM,0))<0)
	{
		perror("socket error\n");
		return -1;
	}

	bzero(&server_ip,sizeof(server_ip));
	//equal to memser()
	server_ip.sin_family  =AF_INET;
	server_ip.sin_addr.s_addr = inet_addr("127.0.0.1");
	server_ip.sin_port = htons(8888);

	if(connect(sockfd,(struct sockaddr*)&server_ip,sizeof(server_ip))<0)
	{
		perror("connect error\n");
		return 0;
	}
	
	bzero(&buf,100);
	strcpy(buf,(char *)"I am client");
	if(write(sockfd,buf,strlen(buf))<0)
	{
		printf("error,write error\n");
		return -1;
	}
	
	bzero(&buf,100);
	bytes = read(sockfd,buf,100);
	if(bytes<0)
	{
		printf("error,read failed\n");
		return -1;
	}

	if(bytes ==0)
	{
		printf("Server close connection\n");
		return -1;
	}

	if(bytes >0)
	{
		printf("read bytes %d\n",bytes);
		printf("time is %s\n",buf);
	}
	
	close(sockfd);
	return 0;
}


注意:server中添加了setsockopt函数
#include <sys/types.h>
#include <sys/socket.h>
int setsockopt(int sockfd, int level, int optname,const void *optval, socklen_t optlen);
如果运行server的时候,若未正常退出内核有时候会提示地址已经在使用,此时可用此函数来重用地址,否则在几分钟内无法重启server的。





  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

昕光xg

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值