简单的TCP服务器与客户端

参考《unix 网络编程 卷1》与 点击打开链接

需要提前了解:

1.协议方面:三次握手建立连接、四次握手断开连接

2.通信流程:请参考点击打开链接

3.fork()、read()(也可以用recv()函数)、write()(也可以用send()函数)


服务器:

#include <stdio.h>
#include <sys/socket.h>
#include <unistd.h>// read()
#include <arpa/inet.h>//htonl htons
#include <string.h>//bzero
#include <stdlib.h>

#define servport 8000
#define BACKLOG 5
#define MAXBUF 100
#define true 1

int main(){
	int listenfd,connfd;
	struct sockaddr_in servaddr,cliaddr;
	socklen_t addrlen;
	pid_t pid;
	int n;
	char buf[100] = {0};
	// ssize_t n;

	printf("child process run from main()?");
	//socket description,TCP,byte stream
	if ( (listenfd = socket(AF_INET,SOCK_STREAM,0)) == -1){
		perror("listenfd establish error");
		exit(1);
	}

	//set sercaddr
	bzero(&servaddr,sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_addr.s_addr = htonl(INADDR_ANY);
	servaddr.sin_port = htons(servport);
	
	//bind socket
	if(bind(listenfd, (struct sockaddr *)&servaddr, sizeof(servaddr)) == -1){  
		perror("bind error");  
		exit(1);  
    }

    //listen
    if(listen(listenfd,BACKLOG)== -1){  /* calls listen() */  
		perror("listen error\n");  
		exit(1);
	}

	//accept
	while(true){
		if( ( connfd = accept(listenfd, (struct sockaddr*)&cliaddr, &addrlen) ) == -1 ){
			perror("accept error\n");
			exit(1);
		}
		if( ( pid = fork() ) == 0 ){
			close(listenfd);
			while( (n = read(connfd, buf, MAXBUF) > 0 ) ){
				printf("read complete %s\n",buf);
			}
			close(connfd);// you can comment this line because "exit(0)" will close connfd too
			exit(0);
		}
		close(connfd);
	}
	return 0;
}
客户端:

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <unistd.h>

//inet_pton
#include <netinet/in.h>
#include <arpa/inet.h>//htons htonl
#include <string.h>//bzero

#define servport 8000
int main(int argc, char **argv){
	int sockfd;
	char buf[100] = "Hello!";
	struct sockaddr_in servaddr;
	
	if(argc!=2){
		perror("usage: IPaddress");
		exit(1);
	}
	if ( ( sockfd = socket(AF_INET,SOCK_STREAM,0) ) == -1){
		perror("socket establish error");
		exit(1);
	}
	bzero(&servaddr,sizeof(servaddr));
	servaddr.sin_family = AF_INET;
	servaddr.sin_port = htons(servport);
	inet_pton(AF_INET, argv[1], &servaddr.sin_addr);

	if ( connect( sockfd, (struct sockaddr *)&servaddr, sizeof(servaddr) ) == -1 ){
		perror("connect failed");
		exit(1);
	}

	if ( write(sockfd, buf, sizeof(buf)) == -1){
		perror("send error");
		exit(1);
	}
	close(sockfd);
	exit(0);
	return 0;
}

为了方便写了个Makefile:

all: server client


server: myserver.c
	gcc -W -Wall -o server myserver.c


client: myclient.c
	gcc -W -Wall -o client myclient.c


clean:
	rm server client
make后运行:

./server

./client 127.0.0.1

运行结果:



目前不知道为什么“child process run from main()?”只打印了一遍,还要再去了解下fork()函数,猜想是父进程与子进程各打印一遍的,不过说起来控制台能把父进程、子进程的打印内容都打印一遍吗?


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值