tcp_server_mulpthread.c
#include <signal.h>
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <time.h>
#include <pthread.h>
#include <string.h>
#include <sys/wait.h>
#include <arpa/inet.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
//int socket(int domain, int type, int protocol);
//typedef void (*sighandler_t)(int);
//sighandler_t signal(int signum, sighandler_t handler);
//void perror(const char *s);
int socket_fd;
void sig_fun(int signo)
{
if(signo == SIGINT){
printf("signal = %d\n",signo);
close(socket_fd);
exit(1);
}
}
void out_fd(int fd)
{
struct sockaddr_in addr;
socklen_t len = sizeof(addr);
if(getpeername(fd, (struct sockaddr *)&addr, &len) <0){
perror("getpeername");
}
int port = ntohs(addr.sin_port);
char ip[16];
if(inet_ntop(AF_INET, &addr.sin_addr.s_addr, ip ,16) == NULL){
perror("out_addr:");
}
printf("cliet:%s(%d)\n",ip,port);
return ;
}
void do_service(int fd)
{
char buffer[512];
while(1){
/*相当于不完整管道
*如果服务器从socket中读取到的数据为0,说明客户端关闭了socket或客户端已经挂掉了(服务器读一个写端关闭了的socket)
*如果服务器往读端(客户端)关闭了的socket中写数据,将会产生一个SIGPIPE的信号,并且errorno被设置为EPIPE(服务器写一个读端关闭了的socket)
*/
memset(buffer, 0, sizeof(buffer));
ssize_t size;
if((size = read(fd, buffer, sizeof(buffer))) < 0){
perror("read:");
break;
}else if(size == 0){
break;
}else{
//write(STDOUT_FILENO, buffer, sizeof(buffer));
printf("%s(%ld)\n",buffer,size);
if(write(fd, buffer, sizeof(buffer)) <0 ){
if(errno == EPIPE){
printf("erro");
break;
}
perror("write:");
}
}
}
}
void *th_fun(void *arg)
{
long fd = (long)arg;
printf("fd2=%ld\n",fd);
out_fd(fd);
do_service(fd);
close(fd);
return (void *)0;
}
int main(int argc,char *argv[])
{
if(argc <2){
perror("argc<2:");
exit(1);
}
if(signal(SIGINT,sig_fun) == SIG_ERR){
perror("signal:");
exit(1);
}
/*
*1. 创建socket
*/
if((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
perror("socket:");
exit(1);
}
/*
*2.绑定IP地址和端口号
*int bind(int sockfd, const struct sockaddr *addr,socklen_t addrlen);
*/
struct sockaddr_in serviceaddr;
memset(&serviceaddr, 0, sizeof(serviceaddr));
serviceaddr.sin_family = AF_INET;
serviceaddr.sin_port = htons(atoi(argv[1]));
serviceaddr.sin_addr.s_addr = INADDR_ANY;//一台服务器上可能有多块网卡(多个IP地址)
//这个宏是响应本机所有网卡(IP地址)上连接的客户端请求
if(bind(socket_fd, (struct sockaddr *)&serviceaddr, sizeof(serviceaddr)) < 0){
perror("bind:");
exit(1);
};
/*
*3.监听绑定的端口
*通知系统去监听来自客户端的连接请求
*(将监听到的客户端连接请求放置到对应的队列中)
*第二个参数:指定队列的长度
*/
if(listen(socket_fd, 10) < 0){
perror("listen:");
exit(1);
}
/*
*4.调用accept函数从队列中获得一个客户端的连接请求
*并返回一个新的socket描述符,这个描述符和和客户端
*的连接请求对应,即这个描述符和某个客户端对应
*如果没有客户端连接,调用此函数会阻塞,直到获得一个客户端的连接
*第二个参数:客户端的地址信息
*/
pthread_attr_t attr;
pthread_attr_init(&attr);
pthread_attr_setdetachstate(&attr,PTHREAD_CREATE_DETACHED);
pthread_t t;
while(1){
int fd = accept(socket_fd, NULL, NULL);
if(fd < 0){
perror("accept:");
continue;
}
/*
*5.创建子线程进行并发处理
*int pthread_create(pthread_t *thread, const pthread_attr_t *attr,
* void *(*start_routine) (void *), void *arg);
*/
if(pthread_create(&t, &attr, th_fun, (void *)(long)fd) != 0){
perror("pthread_create");
continue;
}
pthread_attr_destroy(&attr);
printf("t = %ld\n",t); //t的值不同,因为每创建一个线程就会给t重新赋值
printf("fd1=%d\n",fd);//fd的值不同,因为没接受到一个客户端,就会返回一个不同的值
}
return 0;
}
tcp_client_mulpthread.c
#include <stdio.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h>
#include <string.h>
#include <arpa/inet.h>
#include <sys/types.h> /* See NOTES */
#include <sys/socket.h>
int main(int argc, char *argv[])
{
int socket_fd;
if(argc < 2){
printf("参数太少");
exit(1);
}
//1.创建socket
if((socket_fd = socket(AF_INET, SOCK_STREAM, 0)) < 0){
perror("socket:");
exit(1);
}
//2. 连接服务器
struct sockaddr_in serviceaddr;
memset(&serviceaddr, 0, sizeof(serviceaddr));
serviceaddr.sin_family = AF_INET;
serviceaddr.sin_port = htons(atoi(argv[2]));
if(inet_pton(AF_INET, argv[2], &serviceaddr.sin_addr.s_addr) < 0){
perror("inet_pton:");
exit(1);
}
if(connect(socket_fd, (struct sockaddr *)&serviceaddr, sizeof(serviceaddr)) < 0){
perror("connect");
exit(1);
}
//3. read/write
char buff[512];
size_t size;
char *s = ">";
while(1){
write(STDOUT_FILENO, s, 1);
memset(buff, 0, 1024);
size = read(STDIN_FILENO, buff, sizeof(buff));
if(size <0 ) continue;
buff[size -1] = '\0';
if(write(socket_fd, buff, sizeof(buff)) < 0){
perror("write");
}else{
if(read(socket_fd, buff, sizeof(buff)) <0){
perror("read");
continue;
}else{
printf("%s\n",buff);
}
}
}
//关闭套接字
close(socket_fd);
return 0;
}