Linux 网络编程四(socket多线程升级版)
生活随笔
收集整理的這篇文章主要介紹了
Linux 网络编程四(socket多线程升级版)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
//網絡編程--客戶端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>/*強調:當客戶端連接服務器時,服務器會產生一個新的文件描述符(套接字)與客戶端交互,這個新的套接字不是服務器端的監聽套接字套接字是全雙工的,在一個網絡管道中的兩端,每端都可以進行讀寫操作。*/typedef struct _recvmodel
{int st;struct sockaddr_in * addr;
} RecvModel;//send message
void * send_thread(void *arg)
{if (arg == NULL){printf("param is not allow NULL!\n");return NULL;}int st = *(int *) arg;char buf[1024] = { 0 };while (1){read(STDIN_FILENO, buf, sizeof(buf));if (send(st, buf, strlen(buf), 0) == -1){printf("send failed ! error message %s\n", strerror(errno));return NULL;}memset(buf, 0, sizeof(buf));}return NULL;
}//recv message
void * recv_thread(void * arg)
{if (arg == NULL){printf("param is not allow NULL!\n");return NULL;}RecvModel * model = (RecvModel *) arg;int flag = 0;char buf[1024] = { 0 };while (1){flag = recv(model->st, buf, sizeof(buf), 0);if (flag == 0){printf("對方已經關閉連接!\n");return NULL;} else if (flag == -1){printf("recv failed ! error message : %s\n", strerror(errno));return NULL;}printf("from %s:%s", inet_ntoa(model->addr->sin_addr), buf);memset(buf, 0, sizeof(buf));}return NULL;
}int main(int arg, char *args[])
{//打開socketint st = socket(AF_INET, SOCK_STREAM, 0);if (st == -1){printf("open socket failed! error message:%s\n", strerror(errno));return -1;}//定義IP地址結構struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));//設置TCP/IP連接addr.sin_family=AF_INET;//設置端口號addr.sin_port = htons(8080);//設置允許連接地址addr.sin_addr.s_addr = inet_addr("192.168.1.102");//connect serverint numx = connect(st, (struct sockaddr *) &addr, sizeof(addr));if (numx == -1){printf("connect server failed ! error message :%s\n", strerror(errno));goto END;}RecvModel model;model.st = st;model.addr = &addr;//開啟多線程--線程1接收消息,線程2發送消息
pthread_t thr1, thr2;if (pthread_create(&thr1, NULL, send_thread, &st) != 0){printf("create thread failed ! \n");goto END;}if (pthread_create(&thr2, NULL, recv_thread, &model) != 0){printf("create thread failed ! \n");goto END;}pthread_join(thr1, NULL);pthread_join(thr2, NULL);END: close(st);return 0;
} //網絡編程--服務端
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <unistd.h>
#include <errno.h>#include <sys/types.h>
#include <sys/socket.h>
#include <pthread.h>
#include <netinet/in.h>
#include <arpa/inet.h>typedef struct _recvmodel
{int st;struct sockaddr_in * addr;
} RecvModel;//send message
void * send_thread(void *arg)
{if (arg == NULL){printf("param is not allow NULL!\n");return NULL;}int st = *(int *) arg;char buf[1024] = { 0 };while (1){read(STDIN_FILENO, buf, sizeof(buf));if (send(st, buf, strlen(buf), 0) == -1){printf("send failed ! error message %s\n", strerror(errno));return NULL;}memset(buf, 0, sizeof(buf));}return NULL;
}//recv message
void * recv_thread(void * arg)
{if (arg == NULL){printf("param is not allow NULL!\n");return NULL;}RecvModel * model = (RecvModel *) arg;int flag = 0;char buf[1024] = { 0 };while (1){flag = recv(model->st, buf, sizeof(buf), 0);if (flag == 0){printf("對方已經關閉連接!\n");return NULL;} else if (flag == -1){printf("recv failed ! error message : %s\n", strerror(errno));return NULL;}printf("from %s:%s", inet_ntoa(model->addr->sin_addr), buf);memset(buf, 0, sizeof(buf));}return NULL;
}int main(int arg, char *args[])
{//short port = atoi(args[1]);//打開socketint st = socket(AF_INET, SOCK_STREAM, 0);if (st == -1){printf("open socket failed! error message:%s\n", strerror(errno));return -1;}//設置系統地址可重用int on = 1;if (setsockopt(st, SOL_SOCKET, SO_REUSEADDR, &on, sizeof(on)) == -1){printf("setsockpot failed ! error message %s\n", strerror(errno));goto END;}//定義IP地址結構struct sockaddr_in addr;memset(&addr, 0, sizeof(addr));//設置TCP/IP連接addr.sin_family = AF_INET;//設置端口號addr.sin_port = htons(8080);//設置允許連接地址addr.sin_addr.s_addr = htonl(INADDR_ANY);//bind ipif (bind(st, (struct sockaddr *) &addr, sizeof(addr)) == -1){printf("bind ip failed ! error message :%s\n", strerror(errno));goto END;}//監聽連接if (listen(st, 20) == -1){printf("listen failed ! error message :%s\n", strerror(errno));goto END;}//接收客戶端連接(阻塞)struct sockaddr_in client_addr;memset(&client_addr, 0, sizeof(client_addr));socklen_t client_addrlen = sizeof(client_addr);
//強調:這里的client_addrlen并不是為了在函數中設置client_addrlen的值,而是通過client_addrlen的值來判斷client_addr是一個什么類型的結構,
//所以這里client_addrlen設置為0是錯誤的,必須是struct sockaddr_in這個結構的大小,不然返回值不正確int client_st = accept(st, (struct sockaddr *) &client_addr,&client_addrlen);if (client_st == -1){printf("accept failed ! error message :%s\n", strerror(errno));goto END;}RecvModel model;model.st = client_st;model.addr = &client_addr;printf("accept by=%s\n",inet_ntoa(client_addr.sin_addr));//開啟多線程--線程1接收消息,線程2發送消息 pthread_t thr1, thr2;if (pthread_create(&thr1, NULL, send_thread, &client_st) != 0){printf("create thread failed ! \n");goto END;}if (pthread_create(&thr2, NULL, recv_thread, &model) != 0){printf("create thread failed ! \n");goto END;}pthread_join(thr1, NULL);pthread_join(thr2, NULL);//關閉客戶端管道 close(client_st);END: close(st);return 0; } .SUFFIXES:.c .o CC=gcc SRCS1=mserver.c SRCS2=mclient.c OBJS1=$(SRCS1:.c=.o) OBJS2=$(SRCS2:.c=.o) EXEC1=mserv EXEC2=mclistart:$(OBJS1) $(OBJS2)$(CC) -o $(EXEC1) $(OBJS1) -lpthread$(CC) -o $(EXEC2) $(OBJS2) -lpthread@echo "^_^ ------ OK ------ ^_^" .c.o:$(CC) -Wall -g -o $@ -c $< clean:rm -f $(OBJS1)rm -f $(OBJS2)rm -f $(EXEC1)rm -f $(EXEC2) 小結:這段升級版程序花費3小時,出現一個錯誤提示:"?Transport endpoint is not connected",我仔細查找資料,
網上說是socket套接字不對,可我程序中套接字是正確的,
我沒有辦法,但是我有一個成功的程序,就是第一版socket程序,我將原來的socket程序復制到我的新程序中,一句句替換,終于發現這個問題
問題:我缺少addr.sin_family = AF_INET;//將網絡地址類型設置為TCP/IP協議;這句代碼。缺少這段代碼是導致報錯的主要原因。
另外注意我代碼中強調的內容--網絡管道是全雙工的
//強調:這里的client_addrlen并不是為了在函數中設置client_addrlen的值,而是通過client_addrlen的值來判斷client_addr是一個什么類型的結構,
//所以這里client_addrlen設置為0是錯誤的,必須是struct sockaddr_in這個結構的大小,不然返回值不正確int client_st = accept(st, (struct sockaddr *) &client_addr,&client_addrlen);if (client_st == -1){printf("accept failed ! error message :%s\n", strerror(errno));goto END;}RecvModel model;model.st = client_st;model.addr = &client_addr;printf("accept by=%s\n",inet_ntoa(client_addr.sin_addr));//開啟多線程--線程1接收消息,線程2發送消息 pthread_t thr1, thr2;if (pthread_create(&thr1, NULL, send_thread, &client_st) != 0){printf("create thread failed ! \n");goto END;}if (pthread_create(&thr2, NULL, recv_thread, &model) != 0){printf("create thread failed ! \n");goto END;}pthread_join(thr1, NULL);pthread_join(thr2, NULL);//關閉客戶端管道 close(client_st);END: close(st);return 0; } .SUFFIXES:.c .o CC=gcc SRCS1=mserver.c SRCS2=mclient.c OBJS1=$(SRCS1:.c=.o) OBJS2=$(SRCS2:.c=.o) EXEC1=mserv EXEC2=mclistart:$(OBJS1) $(OBJS2)$(CC) -o $(EXEC1) $(OBJS1) -lpthread$(CC) -o $(EXEC2) $(OBJS2) -lpthread@echo "^_^ ------ OK ------ ^_^" .c.o:$(CC) -Wall -g -o $@ -c $< clean:rm -f $(OBJS1)rm -f $(OBJS2)rm -f $(EXEC1)rm -f $(EXEC2) 小結:這段升級版程序花費3小時,出現一個錯誤提示:"?Transport endpoint is not connected",我仔細查找資料,
網上說是socket套接字不對,可我程序中套接字是正確的,
我沒有辦法,但是我有一個成功的程序,就是第一版socket程序,我將原來的socket程序復制到我的新程序中,一句句替換,終于發現這個問題
問題:我缺少addr.sin_family = AF_INET;//將網絡地址類型設置為TCP/IP協議;這句代碼。缺少這段代碼是導致報錯的主要原因。
另外注意我代碼中強調的內容--網絡管道是全雙工的
?
轉載于:https://www.cnblogs.com/zhanggaofeng/p/5877617.html
與50位技術專家面對面20年技術見證,附贈技術全景圖總結
以上是生活随笔為你收集整理的Linux 网络编程四(socket多线程升级版)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: mybatis报错invalid typ
- 下一篇: 谈一下JavaScript的语法