参考《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()函数,猜想是父进程与子进程各打印一遍的,不过说起来控制台能把父进程、子进程的打印内容都打印一遍吗?