初学linux的socket编程,写几个简单的小实例。
程序在http://download.csdn.net/download/longmenwaideyu/8112301 和 https://github.com/longmenwaideyu/linuxUDPChatroom都可以下载
chatServer.c
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <arpa/inet.h> #include <time.h> #include <pthread.h> #include "chatmsg.h" #define SERVER_PORT 8888 #define MAX_MSG_SIZE 1024 struct sockaddr_in addrlist[1000]; int useridlist[1000]; time_t islive[10000]; void *checklive(void *args) { int i; while(1) { sleep(10); for (i = 0; i < 1000; i++) { if (useridlist[i] != -1) { if (time(NULL) - islive[useridlist[i]] >= 20) { useridlist[i] = -1; fprintf(stdout, "%d lost connect\n", useridlist[i]); } } } } } int adduser(struct sockaddr_in addr, int userid){ int i; for (i = 0; i < 1000; i++) { if (useridlist[i] == -1) { addrlist[i] = addr; useridlist[i] = userid; islive[userid] = time(NULL); return 0; } } return -1; } void sendtouser(int sockfd, struct chatmsg msg) { int i; socklen_t addrlen = sizeof(struct sockaddr_in); for (i = 0; i < 1000; i++) { if (useridlist[i] != -1 && useridlist[i] != msg.userid) { sendto(sockfd, (void*)&msg, sizeof(msg), 0, (struct sockaddr*) &addrlist[i], addrlen); } } } void processMsg(int sockfd, struct sockaddr_in addr, struct chatmsg msg) { if (msg.msgtype == CHATMSG_JOIN) { adduser(addr, msg.userid); } else if (msg.msgtype == CHATMSG_CHAT) { sendtouser(sockfd, msg); } else if (msg.msgtype == CHATMSG_HEART) { islive[msg.userid] = time(NULL); } } void start_server(int sockfd) { struct sockaddr_in addr; int n; socklen_t addrlen; struct chatmsg msg; pthread_t th; pthread_create(&th, NULL, checklive, NULL); while (1) { addrlen = sizeof(struct sockaddr_in); n = recvfrom(sockfd, (void *)&msg, sizeof(struct chatmsg), 0, (struct sockaddr*)&addr, &addrlen); if (msg.msgtype == CHATMSG_CHAT) fprintf(stdout, "receved msg from %d: msgid: %d msg: %s", msg.userid, msg.msgid, msg.msgbuf); else if (msg.msgtype == CHATMSG_JOIN) fprintf(stdout, "%d join the room\n", msg.userid); processMsg(sockfd, addr, msg); } } int main () { int i; for (i = 0; i < 1000; i++) { useridlist[i] = -1; } for (i = 0; i < 10000; i++) { islive[i] = time(NULL); } int sockfd; struct sockaddr_in addr; sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { fprintf(stderr, "Socket Error: %s\n", strerror(errno)); exit(1); } bzero(&addr, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_addr.s_addr = htonl(INADDR_ANY); addr.sin_port = htons(SERVER_PORT); if (bind(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { fprintf(stderr, "Bind Error: %s\n", strerror(errno)); exit(1); } start_server(sockfd); close(sockfd); return 0; }
chatClient.c
#include <stdlib.h> #include <stdio.h> #include <errno.h> #include <string.h> #include <unistd.h> #include <netdb.h> #include <sys/socket.h> #include <netinet/in.h> #include <sys/types.h> #include <arpa/inet.h> #include <pthread.h> #include "chatmsg.h" #define SERVER_PORT 8888 #define MAX_MSG_SIZE 1024 int userid, msgid; struct sockinfo { int sockfd; struct sockaddr_in* addr; }; void *heartbeat(void* args) { int sockfd = ((struct sockinfo*)args)->sockfd; struct sockaddr_in* addr = ((struct sockinfo*)args)->addr; struct chatmsg msg; while (1) { sleep(10); msg.userid = userid; msg.msgtype = CHATMSG_HEART; msg.msgid = msgid++; sendto(sockfd, (void*)&msg, sizeof(struct chatmsg), 0, (struct sockaddr*)addr, sizeof(struct sockaddr_in)); } } void *recvchatmsg(void* args) { int sockfd = *(int*)args; struct chatmsg msg; while(1) { int n = recvfrom(sockfd, (void*)&msg, sizeof(struct chatmsg), 0, NULL, NULL); if (n < 0) { fprintf(stderr, "Recv error%s\n", strerror(errno)); } else { fprintf(stdout, "%d:\t%s", msg.userid, msg.msgbuf); } } } void start_client(int sockfd, struct sockaddr_in *addr, socklen_t len) { pthread_t th1, th2; struct sockinfo args; args.sockfd = sockfd; args.addr = addr; pthread_create(&th1, NULL, recvchatmsg, (void*)&sockfd); pthread_create(&th2, NULL, heartbeat, (void*)&args); int n; char buffer[MAX_MSG_SIZE]; struct chatmsg msg; msg.userid = userid; msg.msgid = msgid++; msg.msgtype = CHATMSG_JOIN; sendto(sockfd, (void*)&msg, sizeof(struct chatmsg), 0, (struct sockaddr*)addr, len); while (fgets(buffer, MAX_MSG_SIZE, stdin)) { msg.userid = userid; memcpy(msg.msgbuf, buffer, sizeof(buffer)); msg.msgid = msgid++; msg.msgtype = CHATMSG_CHAT; sendto(sockfd, (void*)&msg, sizeof(struct chatmsg), 0, (struct sockaddr*)addr, len); } } int main (int argc, char **argv) { if (argc != 4) { fprintf(stderr, "usage ip port userid\n"); exit(1); } msgid = 1; int sockfd, port; struct sockaddr_in addr; if ((userid = atoi(argv[3])) < 0) { fprintf(stderr, "usage ip port userid\n"); exit(1); } if ((port = atoi(argv[2])) < 0) { fprintf(stderr, "usage ip port userid\n"); exit(1); } sockfd = socket(AF_INET, SOCK_DGRAM, 0); if (sockfd < 0) { fprintf(stderr, "Socket Error: %s\n", strerror(errno)); exit(1); } bzero(&addr, sizeof(struct sockaddr_in)); addr.sin_family = AF_INET; addr.sin_port = htons(SERVER_PORT); if (inet_aton(argv[1], &addr.sin_addr) < 0) { fprintf(stderr, "IP error\n"); exit(1); } if (connect(sockfd, (struct sockaddr *)&addr, sizeof(struct sockaddr_in)) < 0) { fprintf(stderr, "Connect Error: %s\n", strerror(errno)); exit(1); } start_client(sockfd, &addr, sizeof(struct sockaddr_in)); close(sockfd); return 0; }
chatmsg.h
#define CHATMSG_JOIN 0 #define CHATMSG_EXIT 1 #define CHATMSG_CHAT 2 #define CHATMSG_HEART 3 struct chatmsg { int userid; int msgid; int msgtype; char msgbuf[1024]; };