一、TCP服务器
2、bind()
上一篇文章讲过,struct sockaddr *是一个通用指针类型,
返回值:
3、listen():实现监听
sockfd:listen()声明sockfd处于监听状态,
4、accept():获得连接并建立连接
参数:
如果服务器调用accept()时还没有客户端的连接请求,就阻塞等待直到有客户端连接上来
1 #include
2 #include
3 #include
4 #include
5 #include
6 #include
7 #include
8
9 #define _PORT_ 8080
10 #define _BACKLOG_ 10
11
12 int main(){
13 int sock=socket(AF_INET,SOCK_STREAM,0);
14 if(sock<0){
15 printf("create socket error,error is : %d,errstring is : %s\n",errno,strerror(errno));
16 }
17
18 struct sockaddr_in server_socket;
19 struct sockaddr_in client_socket;
20 bzero(&server_socket,sizeof(server_socket));
21 server_socket.sin_family=AF_INET;
22 server_socket.sin_addr.s_addr=htonl(INADDR_ANY);
23 server_socket.sin_port=htons(_PORT_);
24
25 if(bind(sock,(struct sockaddr*)&server_socket,sizeof(struct sockaddr_in))<0){
26 printf("bind error,error code is : %d,error string is : %s\n",errno,strerror(errno));
27 close(sock);
28 return 1;
29 }
30 if(listen(sock,_BACKLOG_)<0){
31 printf("listen error,error code is : %d,error string is : %s\n",errno,strerror(errno));
32 close(sock);
33 return 2;
34 }
35 printf("bind and listen success,wait accept...\n");
36 for(;;){
37 socklen_t len=0;
38 int client_sock=accept(sock,(struct sockaddr*)&client_socket,&len);
39 if(client_sock<0){
40 printf("accept error,errno is : %d,errstring is:%s\n",errno,strerror(errno));
41 close(sock);
42 return 3;
43 }
44 char buf_ip[INET_ADDRSTRLEN];
45 memset(buf_ip,'\0',sizeof(buf_ip));
46 inet_ntop(AF_INET,&client_socket.sin_addr,buf_ip,sizeof(buf_ip));
47
48 printf("get connect,ip is : %s port is : %d\n",buf_ip,ntohs(client_socket.sin_port));
49 while(1){
50 char buf[1024];
51 memset(buf,'\0',sizeof(buf));
52
53 read(client_sock,buf,sizeof(buf));
54 printf("client :#%s\n",buf);
55
56 printf("server :$ ");
57
58 memset(buf,'\0',sizeof(buf));
59 fgets(buf,sizeof(buf),stdin);
60 buf[strlen(buf)-1]='\0';
61 write(client_sock,buf,strlen(buf)+1);
62 printf("please wait...\n");
63 }
64 }
65 close(sock);
66 return 0;
67 }
68
3、简单实现TCP网络程序客户端:
#include
#include
#include
#include
#include
#include
#include
#include
#define SERVER_PORT 8080
#define SERVER_IP "127.0.0.1"
int main(int argc,char *argv[]){
if(argc!=2){
printf("Usage : client IP\n");
return 1;
}
char *str=argv[1];
char buf[1024];
memset(buf,'\0',sizeof(buf));
struct sockaddr_in server_sock;
int sock=socket(AF_INET,SOCK_STREAM,0);
bzero(&server_sock,sizeof(server_sock));
server_sock.sin_family=AF_INET;
//inet_pton(AF_INET,SERVER_IP,&server_sock.sin_addr);
server_sock.sin_port=htons(SERVER_PORT);
server_sock.sin_addr.s_addr=inet_addr(SERVER_IP);
int ret=connect(sock,(struct sockaddr *)&server_sock,sizeof(server_sock));
if(ret<0){
printf("connect failed...,errno is : %d,errstring is : %s\n",errno,strerror(errno));
return 1;
}
printf("connect success...\n");
while(1){
printf("client : # ");
fgets(buf,sizeof(buf),stdin);
buf[strlen(buf)-1]='\0';
write(sock,buf,sizeof(buf));
if(strncasecmp(buf,"quit",4)==0){
printf("quit!\n");
break;
}
printf("please wait...\n");
read(sock,buf,sizeof(buf));
printf("server :$ %s\n",buf);
}
close(sock);
return 0;
}
服务器端代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
void Usage(){
printf("usage : ./server [ip][port]\n");
}
void ProcessRequest(int client_fd,struct sockaddr_in* client_addr){
char buf[1024]={0};
for(;;){
ssize_t read_size=read(client_fd,buf,sizeof(buf));
if(read_size<0){
perror("read");
continue;
}
if(read_size==0){
printf("client: %s say bye!\n",inet_ntoa(client_addr->sin_addr));
close(client_fd);
break;
}
buf[read_size]='\0';
printf("client %s say: %s\n",inet_ntoa(client_addr->sin_addr),buf);
write(client_fd,buf,strlen(buf));
}
}
void CreateWorker(int client_fd,struct sockaddr_in* client_addr){
pid_t pid=fork();
if(pid<0){
perror("fork");
return;
}else if(pid==0){
//child
if(fork()==0){
//grand_child
ProcessRequest(client_fd,client_addr);
}
exit(0);
}
else{
//father
close(client_fd);
waitpid(pid,NULL,0);
}
}
int main(int argc,char* argv[]){
if(argc!=3){
Usage();
return 1;
}
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(argv[1]);
addr.sin_port=htons(atoi(argv[2]));
int fd=socket(AF_INET,SOCK_STREAM,0);
if(fd<0){
perror("socket");
return 1;
}
int ret=bind(fd,(struct sockaddr*)&addr,sizeof(addr));
if(ret<0){
perror("bind");
return 1;
}
ret=listen(fd,10);
if(ret<0){
perror("listen");
return 1;
}
for(;;){
struct sockaddr_in client_addr;
socklen_t len=sizeof(client_addr);
int client_fd=accept(fd,(struct sockaddr*)&client_addr,&len);
if(client_fd<0){
perror("accept");
continue;
}
char bufip[32];
bufip[0]=0;
inet_ntop(AF_INET,&client_addr.sin_addr,bufip,sizeof(bufip));
printf("get connect,ip is:%s port is:%d\n",bufip,ntohs(client_addr.sin_port));
CreateWorker(client_fd,&client_addr);
}
close(fd);
return 0;
}
(2)多进程服务器同时服务的人数有上限,且十分占用资源
(3)进程增多会导致切换成本太大,进而影响性能。
优点:
要实现多线程的TCP,我们必须调用pthread_create函数创建新线程。多线程TCP需要创建线程就可以了,与多进程主逻辑不变。
服务器端代码如下:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
void Usage(){
printf("usage : ./server [ip][port]\n");
}
void ProcessRequest(int client_fd,struct sockaddr_in* client_addr){
char buf[1024]={0};
for(;;){
ssize_t read_size=read(client_fd,buf,sizeof(buf));
if(read_size<0){
perror("read");
continue;
}
if(read_size==0){
printf("client: %s say bye!\n",inet_ntoa(client_addr->sin_addr));
close(client_fd);
break;
}
buf[read_size]='\0';
printf("client %s say: %s\n",inet_ntoa(client_addr->sin_addr),buf);
write(client_fd,buf,strlen(buf));
}
}
typedef struct ARG{
int fd;
struct sockaddr_in addr;
}Arg;
void* CreateWorker(void *ptr){
Arg* arg=(Arg*)ptr;
ProcessRequest(arg->fd,&arg->addr);
free(arg);
return NULL;
}
int main(int argc,char* argv[]){
if(argc!=3){
Usage();
return 1;
}
struct sockaddr_in addr;
addr.sin_family=AF_INET;
addr.sin_addr.s_addr=inet_addr(argv[1]);
addr.sin_port=htons(atoi(argv[2]));
int fd=socket(AF_INET,SOCK_STREAM,0);
if(fd<0){
perror("socket");
return 1;
}
int ret=bind(fd,(struct sockaddr*)&addr,sizeof(addr));
printf("qqq");
if(ret<0){
perror("bind");
return 1;
}
printf("qqq");
ret=listen(fd,10);
if(ret<0){
perror("listen");
return 1;
}
for(;;){
struct sockaddr_in client_addr;
socklen_t len=sizeof(client_addr);
int client_fd=accept(fd,(struct sockaddr*)&client_addr,&len);
if(client_fd<0){
perror("accept");
continue;
}
char bufip[32];
bufip[0]=0;
inet_ntop(AF_INET,&client_addr.sin_addr,bufip,sizeof(bufip));
printf("get connect,ip is : %s port is :%d\n",bufip,ntohs(client_addr.sin_port));
pthread_t tid=0;
Arg* arg=(Arg*)malloc(sizeof(Arg));
arg->fd=client_fd;
arg->addr=client_addr;
pthread_create(&tid,NULL,CreateWorker,(void*)arg);
pthread_detach(tid);
}
close(fd);
return 0;
}