1.进程
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <signal.h>
#define SER_PORT 6666 #define SER_IP "192.168.124.33" //"0.0.0.0"
int deal_cli_msg(int newfd,struct sockaddr_in cin); void signal_handle(int signum);
int main(int argc, const char *argv[]) { //创建流式套接字 int sfd = socket(AF_INET, SOCK_STREAM, 0); if(sfd < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("socket"); return -1; } printf("socket success __%d__\\n", __LINE__);
//允许端口快速重用 int reuse = 1; if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("setsockopt"); return -1; } printf("reuseaddr success __%d__\\n", __LINE__);
//若从命令行传入端口号,则使用传入的端口号,没有传入则使用宏定义的端口号 int port = argc>=2?atoi(argv[1]):SER_PORT;
//填充服务器的地址信息结构体,给bind函数使用 //真实的地址信息结构体根据地址族指定 AF_INET: man 7 ip struct sockaddr_in sin; sin.sin_family = AF_INET; //必须填AF_INET sin.sin_port = htons(port); //端口号的网络字节序,1024~49151 sin.sin_addr.s_addr = inet_addr(SER_IP); //本机IP的网络字节序,ifconfig查看本机IP //127.0.0.1:本地换回IP,只能做本机通信的IP //0.0.0.0 : 代表运行环境中所有可用IP
//绑定服务器自身的地址信息 if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("bind"); return -1; } printf("bind success __%d__\\n", __LINE__);
//将套接字设置为被动监听状态 if(listen(sfd, 128) < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("listen"); return -1; } printf("listen success __%d__\\n", __LINE__);
//阻塞等待客户端连接成功,从已完成连接的队列头中获取一个客户端信息, //生成一个新的文件描述符,这个新的文件描述符才是与客户端通信用的文件描述符 struct sockaddr_in cin; //存储获取到的客户端的地址信息 socklen_t addrlen = sizeof(cin);
int newfd=-1; pid_t pid=0; signal(SIGCHLD, signal_handle); while(1) { newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen); if(newfd < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("accpet"); return -1; } printf("client connect success, [%s:%d] newfd = %d __%d__\\n", \\ inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, __LINE__);
pid=fork(); if(pid==0) { close(sfd); deal_cli_msg(newfd,cin); close(newfd); exit(0); } close(newfd); } //关闭 close(sfd);
return 0; }
int deal_cli_msg(int newfd,struct sockaddr_in cin) { char buf[128] = ""; ssize_t res = 0; while(1) { bzero(buf, sizeof(buf)); //memset(buf, 0, sizeof(buf)); //收 res = recv(newfd, buf, sizeof(buf), 0); if(res < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("recv"); return -1; } else if(0 == res) { printf("client [%s:%d] offline __%d__\\n",\\ inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), __LINE__); break; }
printf("[%s:%d] newfd=%d : %s\\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, buf);
//发 strcat(buf, ">_<"); if(send(newfd, buf, sizeof(buf), 0) < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("send"); return -1; } printf("send success __%d__\\n", __LINE__); } }
void signal_handle(int signum) { int status; if(signum == SIGCHLD){ int ret = wait( &status); if(ret < 0 ){ perror("wait error"); return ; } } printf("fataher found subprocess exit %d\\n", (signed char) ((status >>8)&0xFF ) ); }
1.线程
#include <stdio.h> #include <sys/types.h> #include <sys/socket.h> #include <arpa/inet.h> #include <netinet/in.h> #include <string.h> #include <unistd.h> #include <stdlib.h> #include <pthread.h>
#define SER_PORT 6666 #define SER_IP "192.168.124.33" //"0.0.0.0"
struct thread_data { pthread_t tid; int newfd; struct sockaddr_in cin; }; void* thead_handle_fun(void* arg);
int main(int argc, const char *argv[]) { //创建流式套接字 int sfd = socket(AF_INET, SOCK_STREAM, 0); if(sfd < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("socket"); return -1; } printf("socket success __%d__\\n", __LINE__);
//允许端口快速重用 int reuse = 1; if(setsockopt(sfd, SOL_SOCKET, SO_REUSEADDR, &reuse, sizeof(reuse)) < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("setsockopt"); return -1; } printf("reuseaddr success __%d__\\n", __LINE__);
//若从命令行传入端口号,则使用传入的端口号,没有传入则使用宏定义的端口号 int port = argc>=2?atoi(argv[1]):SER_PORT;
//填充服务器的地址信息结构体,给bind函数使用 //真实的地址信息结构体根据地址族指定 AF_INET: man 7 ip struct sockaddr_in sin; sin.sin_family = AF_INET; //必须填AF_INET sin.sin_port = htons(port); //端口号的网络字节序,1024~49151 sin.sin_addr.s_addr = inet_addr(SER_IP); //本机IP的网络字节序,ifconfig查看本机IP //127.0.0.1:本地换回IP,只能做本机通信的IP //0.0.0.0 : 代表运行环境中所有可用IP
//绑定服务器自身的地址信息 if(bind(sfd, (struct sockaddr*)&sin, sizeof(sin)) < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("bind"); return -1; } printf("bind success __%d__\\n", __LINE__);
//将套接字设置为被动监听状态 if(listen(sfd, 128) < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("listen"); return -1; } printf("listen success __%d__\\n", __LINE__);
//阻塞等待客户端连接成功,从已完成连接的队列头中获取一个客户端信息, //生成一个新的文件描述符,这个新的文件描述符才是与客户端通信用的文件描述符 struct sockaddr_in cin; //存储获取到的客户端的地址信息 socklen_t addrlen = sizeof(cin);
struct thread_data* pdata=malloc(sizeof(*pdata)); memset(pdata,0,sizeof(*pdata)); while(1) { int newfd = accept(sfd, (struct sockaddr*)&cin, &addrlen); if(newfd < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("accpet"); return -1; } printf("client connect success, [%s:%d] newfd = %d __%d__\\n", \\ inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, __LINE__); pdata->newfd=newfd; pdata->cin=cin; int ret = pthread_create(&pdata->tid, NULL, thead_handle_fun ,pdata ); if(ret <0){ perror("create thread err"); return -34; } pthread_detach( pdata->tid);
} close(sfd);
return 0; }
void* thead_handle_fun(void* arg) { struct thread_data *p = arg; int newfd=p->newfd; struct sockaddr_in cin=p->cin; char buf[128] = ""; ssize_t res = 0; while(1) { bzero(buf, sizeof(buf)); //memset(buf, 0, sizeof(buf)); //收 res = recv(newfd, buf, sizeof(buf), 0); if(res < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("recv"); return -1; } else if(0 == res) { printf("client [%s:%d] offline __%d__\\n",\\ inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), __LINE__); break; }
printf("[%s:%d] newfd=%d : %s\\n", inet_ntoa(cin.sin_addr), ntohs(cin.sin_port), newfd, buf);
//发 strcat(buf, ">_<"); if(send(newfd, buf, sizeof(buf), 0) < 0) { fprintf(stderr, "__%d__ ", __LINE__); perror("send"); return -1; } printf("send success __%d__\\n", __LINE__); } close(newfd); }
评论前必须登录!
注册